From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082816; cv=none; d=zohomail.com; s=zohoarc; b=UhSGYjp4Fa2VLqVwtK07egVI2w2wmZwt0bGKFZpDIE1tbSwhmPw8qlTa9oeCQ14kevkOCwwQ4SdjJRMJKdp5TPD2X7n2tXpkdgpDTQhdEQgsdv1b0dhaw4FtNiKCtveioob8RsMGnmcvhBgoEV1KuIT/u1ZedySlx3yjOKLKbfk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082816; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qY9aDXCdvQKlOQpzxCCXLCIfXFIvBpXlP4Of3TlgDT0=; b=e7g8L03rtgBOYbUnkfCPEw9Ui83HU6Z+TGyIjFmWtolubPHA73SE15C0t8F+eyBNra3ASMJmRS5g7GWMk7Q77WY/VJJmgD3sRjLXGp1m+Wvjs8bBriYusJKQyt1pWvdc+fQbNMbXxOBz8dktYkn8H5Tp6hzjQbX+2f7I/m5KkRE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1766082816767648.8504278877448; Thu, 18 Dec 2025 10:33:36 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo3-0003wN-4T; Thu, 18 Dec 2025 13:32:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWImy-0003mR-JS for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:49 -0500 Received: from mail-lf1-x132.google.com ([2a00:1450:4864:20::132]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWImw-0007LK-Dk for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:48 -0500 Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-598eaafa587so1036970e87.3 for ; Thu, 18 Dec 2025 10:31:46 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082704; x=1766687504; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qY9aDXCdvQKlOQpzxCCXLCIfXFIvBpXlP4Of3TlgDT0=; b=frfUp7CztBhrF7bUwQhPdmIX3Zwt/YHXcqjYoMTbmFbJSnHmS1n5jpDeuqsc056G2x GC1JKj99e05SCfdwti1aL5CFbVU6TbLnk3wkl299PQZKoTIXHGYkVqvByFQDM2pvx2uR eotf6k9u/J/JNCn6OYV+2X9xcbywdMHRy8iRCzkdD9FaBSuC8eAsjSmrMzIAuWwEsCbK Af2o2RyuOQ4smzNXwHfeneKyvRgTOIllE1eh85wzZRm2k5ANEa7koftiSGBoFGH73ijO b1BL4L3HDlVjLw/neRPktDmx+mawSWVys+R88pR98V0TiX+6tVU+6eH1n5EOhBG+YByd XqQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082704; x=1766687504; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qY9aDXCdvQKlOQpzxCCXLCIfXFIvBpXlP4Of3TlgDT0=; b=uhaxYmTsj9oeIQsrmOF5ATdkSLaQml3m6+3xCsePdgoBEhnXl8tJJIh3w0ZauKlBiJ QFTDhTwZxnKca3g061VtJFBLB975pme5IlzEOCey0WukFWd339I6XGwlCaDgvqRBYIIf kMuHKnCvSYGBLudocKuFoyGn4WvcsPd/6uZw/pd38jvANPlaw03r5oBNAgDeHor6LWvw S66oTwiAllJNwPt8ze5Ca1BN06DgsQEkCI3xcRuWtYpR7Z0ArLs14W3nT7hXZlm3LvsU PvpHSMf4yKWyxS+EuYHQdbYYq9tuamMAddr7/T0s8EPC3r+vz2Z107OhyWnRh0o7FiUA Bv6Q== X-Gm-Message-State: AOJu0Ywo/cRQ+4xnJ2abYSLffHjPdlFKhE61KBRS7tThM6Z1kjdlwjuk BKA+FU8dbZ/fXoG5W8KTiRck1O9zgcHR3goPmOyVjwyJABRFKLMqefJzCp6WzCkI X-Gm-Gg: AY/fxX4JoovVOafXQ79crc/1qiKl9hefV5pvbK6Et4pxoZHuJ1cpzBO1a7EdytZB50l j7wrMn19TPH8P3wwoaxQs3cEfJ5KlBZBY3KVixJFWQbVwJBh+M4qE2BC4Aa447DS9xJY+SU/1PG z2h0Asy8GAyBEatzd/fX6mCoQvTuJwKgAMDs7qeNLfN8k+Edy1kipxKCd5pqjfMw4+GQhMdTUa3 9CxHH3nSj6jJq3iMAnYcK/wonJckw6S+Ja+0spEYWrctcryXsL9bP5YBlhC6CDhw+aLIyXiTCdc vY9IQdVFBisW21YRXezUr3JM8uWmudMKv4lJUQjfo3fEV1MgHYml0km1t/9UClGxygW9AwLUm6O G2EJNeq1eV9khshlYPDQypy6K4t9dKspkH2NhXHHd88blzq2iI/J3VitnX1bSo7xS+g/YDrUhqT 1yAfwCgY6orOXIMcpQxS6oTGg= X-Google-Smtp-Source: AGHT+IHJ6lbcS8fFShto5gll/FXeeb1NoDPVa5BWh8z711aAmKy1tNvUoNTRCTAyCbvA2jpbTAp3fA== X-Received: by 2002:a05:6512:a96:b0:594:5f00:c0b7 with SMTP id 2adb3069b0e04-59a17d8cf43mr149974e87.15.1766082703963; Thu, 18 Dec 2025 10:31:43 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 1/6] target/riscv: Refactor counter index calculation. Date: Thu, 18 Dec 2025 21:31:16 +0300 Message-ID: <20251218183122.408690-2-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::132; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x132.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:34 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082817500158500 Content-Type: text/plain; charset="utf-8" When working with hpm registers, we need to calculate counter index by csr number. By now it was done manually. Let's add a function -- riscv_pmu_csrno_to_ctr_idx(), which incapsulates this action. Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- target/riscv/cpu_bits.h | 4 +++ target/riscv/csr.c | 73 ++++++++++++++--------------------------- target/riscv/pmu.c | 44 +++++++++++++++++++++++++ target/riscv/pmu.h | 1 + 4 files changed, 73 insertions(+), 49 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index b62dd82fe7..5c3c1af64e 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -1145,6 +1145,10 @@ typedef enum CTRType { /* RISC-V-specific interrupt pending bits. */ #define CPU_INTERRUPT_RNMI CPU_INTERRUPT_TGT_EXT_0 =20 +#define HPM_MCYCLE_IDX 0 +#define HPM_MTIME_IDX 1 +#define HPM_MINSTRET_IDX 2 + /* JVT CSR bits */ #define JVT_MODE 0x3F #define JVT_BASE (~0x3F) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 5c91658c3d..8bdbc71160 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -110,17 +110,8 @@ static RISCVException ctr(CPURISCVState *env, int csrn= o) { #if !defined(CONFIG_USER_ONLY) RISCVCPU *cpu =3D env_archcpu(env); - int ctr_index; - target_ulong ctr_mask; - int base_csrno =3D CSR_CYCLE; - bool rv32 =3D riscv_cpu_mxl(env) =3D=3D MXL_RV32 ? true : false; - - if (rv32 && csrno >=3D CSR_CYCLEH) { - /* Offset for RV32 hpmcounternh counters */ - base_csrno +=3D 0x80; - } - ctr_index =3D csrno - base_csrno; - ctr_mask =3D BIT(ctr_index); + uint32_t ctr_index =3D riscv_pmu_csrno_to_ctr_idx(csrno); + target_ulong ctr_mask =3D BIT(ctr_index); =20 if ((csrno >=3D CSR_CYCLE && csrno <=3D CSR_INSTRET) || (csrno >=3D CSR_CYCLEH && csrno <=3D CSR_INSTRETH)) { @@ -1166,9 +1157,9 @@ static RISCVException write_minstretcfgh(CPURISCVStat= e *env, int csrno, static RISCVException read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) { - int evt_index =3D csrno - CSR_MCOUNTINHIBIT; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); =20 - *val =3D env->mhpmevent_val[evt_index]; + *val =3D env->mhpmevent_val[ctr_idx]; =20 return RISCV_EXCP_NONE; } @@ -1176,14 +1167,15 @@ static RISCVException read_mhpmevent(CPURISCVState = *env, int csrno, static RISCVException write_mhpmevent(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { - int evt_index =3D csrno - CSR_MCOUNTINHIBIT; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + uint64_t mhpmevt_val =3D val; uint64_t inh_avail_mask; =20 if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - env->mhpmevent_val[evt_index] =3D val; + env->mhpmevent_val[ctr_idx] =3D val; mhpmevt_val =3D mhpmevt_val | - ((uint64_t)env->mhpmeventh_val[evt_index] << 32); + ((uint64_t)env->mhpmeventh_val[ctr_idx] << 32); } else { inh_avail_mask =3D ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH; inh_avail_mask |=3D riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH := 0; @@ -1193,10 +1185,10 @@ static RISCVException write_mhpmevent(CPURISCVState= *env, int csrno, inh_avail_mask |=3D (riscv_has_ext(env, RVH) && riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH = : 0; mhpmevt_val =3D val & inh_avail_mask; - env->mhpmevent_val[evt_index] =3D mhpmevt_val; + env->mhpmevent_val[ctr_idx] =3D mhpmevt_val; } =20 - riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + riscv_pmu_update_event_map(env, mhpmevt_val, ctr_idx); =20 return RISCV_EXCP_NONE; } @@ -1204,9 +1196,9 @@ static RISCVException write_mhpmevent(CPURISCVState *= env, int csrno, static RISCVException read_mhpmeventh(CPURISCVState *env, int csrno, target_ulong *val) { - int evt_index =3D csrno - CSR_MHPMEVENT3H + 3; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); =20 - *val =3D env->mhpmeventh_val[evt_index]; + *val =3D env->mhpmeventh_val[ctr_idx]; =20 return RISCV_EXCP_NONE; } @@ -1214,9 +1206,9 @@ static RISCVException read_mhpmeventh(CPURISCVState *= env, int csrno, static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { - int evt_index =3D csrno - CSR_MHPMEVENT3H + 3; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); uint64_t mhpmevth_val; - uint64_t mhpmevt_val =3D env->mhpmevent_val[evt_index]; + uint64_t mhpmevt_val =3D env->mhpmevent_val[ctr_idx]; target_ulong inh_avail_mask =3D (target_ulong)(~MHPMEVENTH_FILTER_MASK= | MHPMEVENTH_BIT_MINH); =20 @@ -1229,9 +1221,9 @@ static RISCVException write_mhpmeventh(CPURISCVState = *env, int csrno, =20 mhpmevth_val =3D val & inh_avail_mask; mhpmevt_val =3D mhpmevt_val | (mhpmevth_val << 32); - env->mhpmeventh_val[evt_index] =3D mhpmevth_val; + env->mhpmeventh_val[ctr_idx] =3D mhpmevth_val; =20 - riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + riscv_pmu_update_event_map(env, mhpmevt_val, ctr_idx); =20 return RISCV_EXCP_NONE; } @@ -1357,7 +1349,7 @@ static RISCVException riscv_pmu_write_ctrh(CPURISCVSt= ate *env, target_ulong val, static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { - int ctr_idx =3D csrno - CSR_MCYCLE; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); =20 return riscv_pmu_write_ctr(env, val, ctr_idx); } @@ -1365,7 +1357,7 @@ static RISCVException write_mhpmcounter(CPURISCVState= *env, int csrno, static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { - int ctr_idx =3D csrno - CSR_MCYCLEH; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); =20 return riscv_pmu_write_ctrh(env, val, ctr_idx); } @@ -1406,33 +1398,16 @@ RISCVException riscv_pmu_read_ctr(CPURISCVState *en= v, target_ulong *val, static RISCVException read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val) { - uint16_t ctr_index; - - if (csrno >=3D CSR_MCYCLE && csrno <=3D CSR_MHPMCOUNTER31) { - ctr_index =3D csrno - CSR_MCYCLE; - } else if (csrno >=3D CSR_CYCLE && csrno <=3D CSR_HPMCOUNTER31) { - ctr_index =3D csrno - CSR_CYCLE; - } else { - return RISCV_EXCP_ILLEGAL_INST; - } - - return riscv_pmu_read_ctr(env, val, false, ctr_index); + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + return riscv_pmu_read_ctr(env, val, false, ctr_idx); } =20 static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) { - uint16_t ctr_index; =20 - if (csrno >=3D CSR_MCYCLEH && csrno <=3D CSR_MHPMCOUNTER31H) { - ctr_index =3D csrno - CSR_MCYCLEH; - } else if (csrno >=3D CSR_CYCLEH && csrno <=3D CSR_HPMCOUNTER31H) { - ctr_index =3D csrno - CSR_CYCLEH; - } else { - return RISCV_EXCP_ILLEGAL_INST; - } - - return riscv_pmu_read_ctr(env, val, true, ctr_index); + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + return riscv_pmu_read_ctr(env, val, true, ctr_idx); } =20 static int rmw_cd_mhpmcounter(CPURISCVState *env, int ctr_idx, @@ -1599,8 +1574,8 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int cf= g_index, target_ulong *val, static RISCVException read_scountovf(CPURISCVState *env, int csrno, target_ulong *val) { - int mhpmevt_start =3D CSR_MHPMEVENT3 - CSR_MCOUNTINHIBIT; - int i; + uint32_t mhpmevt_start =3D riscv_pmu_csrno_to_ctr_idx(CSR_MHPMEVENT3); + uint32_t i; *val =3D 0; target_ulong *mhpm_evt_val; uint64_t of_bit_mask; diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index a68809eef3..b983eadd83 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -600,3 +600,47 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) =20 cpu->pmu_avail_ctrs =3D cpu->cfg.pmu_mask; } + +uint32_t riscv_pmu_csrno_to_ctr_idx(int csrno) +{ + #define CASE_RANGE(low, high, offset) { \ + case (low)...(high): \ + return csrno - (low) + (offset); \ + } + #define HPMCOUNTER_START (HPM_MINSTRET_IDX + 1) + + switch (csrno) { + CASE_RANGE(CSR_MHPMEVENT3, CSR_MHPMEVENT31, HPMCOUNTER_START) + CASE_RANGE(CSR_MHPMEVENT3H, CSR_MHPMEVENT31H, HPMCOUNTER_START) + CASE_RANGE(CSR_HPMCOUNTER3, CSR_HPMCOUNTER31, HPMCOUNTER_START) + CASE_RANGE(CSR_HPMCOUNTER3H, CSR_HPMCOUNTER31H, HPMCOUNTER_START) + CASE_RANGE(CSR_MHPMCOUNTER3, CSR_MHPMCOUNTER31, HPMCOUNTER_START) + CASE_RANGE(CSR_MHPMCOUNTER3H, CSR_MHPMCOUNTER31H, HPMCOUNTER_START) + + case CSR_MCYCLE: + case CSR_MCYCLEH: + case CSR_CYCLE: + case CSR_CYCLEH: + case CSR_MCYCLECFG: + case CSR_MCYCLECFGH: + return HPM_MCYCLE_IDX; + + case CSR_MINSTRET: + case CSR_MINSTRETH: + case CSR_INSTRET: + case CSR_INSTRETH: + case CSR_MINSTRETCFG: + case CSR_MINSTRETCFGH: + return HPM_MINSTRET_IDX; + + case CSR_TIME: + case CSR_TIMEH: + return HPM_MTIME_IDX; + + default: + g_assert_not_reached(); + } + + #undef HPMCOUNTER_START + #undef CASE_RANGE +} diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 3853d0e262..8f019bea9f 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -38,5 +38,6 @@ void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, targ= et_ulong newpriv, bool new_virt); RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, bool upper_half, uint32_t ctr_idx); +uint32_t riscv_pmu_csrno_to_ctr_idx(int csrno); =20 #endif /* RISCV_PMU_H */ --=20 2.51.0 From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082875; cv=none; d=zohomail.com; s=zohoarc; b=S8IHp9QUvAivYsbk1Yg1kYgg8eBcho5LsWS85XxyOgzKHMVsZwR4hHwUMMG0an/9PBRa06XD5itJzRokhYQMhKZbq53eEcHMCfEgYEBCIjgrQFxt5hgPIFIRM4zAHukrccqbthSXQXNwD3knz/Q1m3ZSEdP3tI3cJzVN7VeHuGs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082875; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=bvdG33TRWp8WNQPzYXmaerPpkmBvUESr5mSsOVtQ4Q8=; b=UnAC4oiFScLlbipCRiITctfZxS9pnEKvPlm5fjW3A5MjSEzKBa4nH9D1fJCV9XeapRi4gJw3GPUXrjsw5MVTMemfYCIp8TVcofvbgypipUNdCogcMqGu3pGDQNDY1DgAGKmGko2loBUOa9PaGcEnaxoLbLCpoShF9pyzSdpSk38= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 176608287520872.85689021737699; Thu, 18 Dec 2025 10:34:35 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo7-0003x5-NF; Thu, 18 Dec 2025 13:32:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWImz-0003mY-3O for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:49 -0500 Received: from mail-lf1-x129.google.com ([2a00:1450:4864:20::129]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWImx-0007LQ-6E for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:48 -0500 Received: by mail-lf1-x129.google.com with SMTP id 2adb3069b0e04-59577c4c7c1so1742053e87.1 for ; Thu, 18 Dec 2025 10:31:46 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082705; x=1766687505; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bvdG33TRWp8WNQPzYXmaerPpkmBvUESr5mSsOVtQ4Q8=; b=BuLzkFvwzDkO+rKme4VWoYYghrwHYh0nsrrwPp+YhneQ5Z86FTvg2FI+NYBBfykawS tM0gFN5ZIxHzOAMDqPapwbHNvBfr2QYdAhWOEaEc2YPWsIgPal/RQtsZijISpkM7Z//p OCt/xziRh4IEx7+MhfM7mysqS7y+TCtzDUqL8silsHtBG40ZW5MEhgtNUheB1BthMQYJ GhfNsJ5xAl3szc7EAzZXuHZtoXm2m74mPdEvMMCxpSdmGQm/zOism+tNZ3Y5dWuU9LIX dm26OmL7eO+/XrDeTxwfhaAcFazGbSRsqmySqmgBLep0hBEsSKH+Xo3EkY41UmqSDmsa F63A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082705; x=1766687505; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bvdG33TRWp8WNQPzYXmaerPpkmBvUESr5mSsOVtQ4Q8=; b=pDC0huw1ssAvHwGEYNKZe/XT38y0tCNsamM6+gjbQMVPVyHZMbCd7bNKndoDSCRV+S bJv8KIO/U35vDjMJJaKBXZoZ6w2bLpBbaYNUly6Yn8ePIZCpEjNuqwFStAbET/4qric/ RnNhlC50JW+5nTeD3QjDrjzma90KVzIx5KF6icGSF54eqKADCDxqmfeOFEo6gMcb0d9H et7R6y5kmEN9OSZkUtJ2yfz8l6Iuc51iSTlwu6wY/uGANceUKVKZY1ZuI2jXR8ew+hjm FcBZF4XZHDmTF8WZU4aXPUMY0dBwLekgqVqZopXd1eirWX7bYtXi9lzB2NaUisT8v9Sn kkwA== X-Gm-Message-State: AOJu0Yx75gtKqsKK6S20070LlYowoR6SqHF64RsT7npEyfhyBO7J6z8t bFOnbJ125MeOE58pq4CkWFvAQcmBg22RmuHYKGITFSFAY62r/K4DM4jFD/uLaf9z X-Gm-Gg: AY/fxX6uY8zCMT8xviYrT3AW3Lyy8lLMLI7X8E+Ya2Re1Oy4Y8m5rpFpCmtDEKhxc/X MTkTwKSO8tIgjkD758WUMIIcLZcTR3POFmD0wLdpqIwfUxFHauwi+MukKYBzp/X4pAR22c5HJ/P i6e9yeO1S1r4LajGApZhVeoSiC/Qhxmg81ZUva2opce/7MVCvwbH66KrqBz6kikmhsY+026jhJL aUyEO0yUtctp83cr4DCkbgVVGHGco8dTFjyL2G/ytJfe1O868IbfdburDGFvJT5pmTkukC9mcuX E2AipUhZDpRy6rdIwvM3fA+mdHPAgJNzIYTx4JUOg/m03RgHPP2+OzWj15EQKvycJF42L9ZJFHY 0GuGkUcNY99kXUioP43TDZ76FrWe5RHuQu63rEIc7aoGukhubbXXh5kEitHOidwAdlmOeBMsu4k KBqUM22Aht36PL X-Google-Smtp-Source: AGHT+IEBB/Rsoe4o74O4RaCcS/gINOdKEL5eskNgr6M0dfB3klPawtUMVkEz7op//XGHFJr55NW45g== X-Received: by 2002:a05:6512:3d9e:b0:595:7d7c:59a9 with SMTP id 2adb3069b0e04-59a17d6bb20mr161845e87.22.1766082704953; Thu, 18 Dec 2025 10:31:44 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 2/6] target/riscv: Reimplement Smcdeleg/Ssccfg via read_*, write_* methods Date: Thu, 18 Dec 2025 21:31:17 +0300 Message-ID: <20251218183122.408690-3-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::129; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x129.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:41 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082896993158500 Content-Type: text/plain; charset="utf-8" Methods rmw_cd_mhpmcounter(), rmw_cd_mhpmcounterh(), rmw_cd_mhpmevent(), rmw_cd_mhpmeventh(), rmw_cd_ctr_cfg(), rmw_cd_ctr_cfgh() contain the same code as read_hmpcounter(), write_mhpmcounter(), etc. To avoid the same logic being implemented twice, lets re-call methods from one another. Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- target/riscv/csr.c | 80 +++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 8bdbc71160..81475ec9a3 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1419,9 +1419,9 @@ static int rmw_cd_mhpmcounter(CPURISCVState *env, int= ctr_idx, } =20 if (!wr_mask && val) { - riscv_pmu_read_ctr(env, val, false, ctr_idx); + read_hpmcounter(env, CSR_MCYCLE + ctr_idx, val); } else if (wr_mask) { - riscv_pmu_write_ctr(env, new_val, ctr_idx); + write_mhpmcounter(env, CSR_MCYCLE + ctr_idx, new_val, 0); } else { return -EINVAL; } @@ -1438,9 +1438,9 @@ static int rmw_cd_mhpmcounterh(CPURISCVState *env, in= t ctr_idx, } =20 if (!wr_mask && val) { - riscv_pmu_read_ctr(env, val, true, ctr_idx); + read_hpmcounterh(env, CSR_MCYCLEH + ctr_idx, val); } else if (wr_mask) { - riscv_pmu_write_ctrh(env, new_val, ctr_idx); + write_mhpmcounterh(env, CSR_MCYCLEH + ctr_idx, new_val, 0); } else { return -EINVAL; } @@ -1448,31 +1448,18 @@ static int rmw_cd_mhpmcounterh(CPURISCVState *env, = int ctr_idx, return 0; } =20 -static int rmw_cd_mhpmevent(CPURISCVState *env, int evt_index, +static int rmw_cd_mhpmevent(CPURISCVState *env, int ctr_idx, target_ulong *val, target_ulong new_val, target_ulong wr_mask) { - uint64_t mhpmevt_val =3D new_val; - if (wr_mask !=3D 0 && wr_mask !=3D -1) { return -EINVAL; } =20 if (!wr_mask && val) { - *val =3D env->mhpmevent_val[evt_index]; - if (riscv_cpu_cfg(env)->ext_sscofpmf) { - *val &=3D ~MHPMEVENT_BIT_MINH; - } + read_mhpmevent(env, ctr_idx - 3 + CSR_MHPMEVENT3, val); } else if (wr_mask) { - wr_mask &=3D ~MHPMEVENT_BIT_MINH; - mhpmevt_val =3D (new_val & wr_mask) | - (env->mhpmevent_val[evt_index] & ~wr_mask); - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - mhpmevt_val =3D mhpmevt_val | - ((uint64_t)env->mhpmeventh_val[evt_index] << 32); - } - env->mhpmevent_val[evt_index] =3D mhpmevt_val; - riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + write_mhpmevent(env, ctr_idx - 3 + CSR_MHPMEVENT3, new_val, 0); } else { return -EINVAL; } @@ -1480,29 +1467,18 @@ static int rmw_cd_mhpmevent(CPURISCVState *env, int= evt_index, return 0; } =20 -static int rmw_cd_mhpmeventh(CPURISCVState *env, int evt_index, +static int rmw_cd_mhpmeventh(CPURISCVState *env, int ctr_idx, target_ulong *val, target_ulong new_val, target_ulong wr_mask) { - uint64_t mhpmevth_val; - uint64_t mhpmevt_val =3D env->mhpmevent_val[evt_index]; - if (wr_mask !=3D 0 && wr_mask !=3D -1) { return -EINVAL; } =20 if (!wr_mask && val) { - *val =3D env->mhpmeventh_val[evt_index]; - if (riscv_cpu_cfg(env)->ext_sscofpmf) { - *val &=3D ~MHPMEVENTH_BIT_MINH; - } + read_mhpmeventh(env, ctr_idx - 3 + CSR_MHPMEVENT3H, val); } else if (wr_mask) { - wr_mask &=3D ~MHPMEVENTH_BIT_MINH; - env->mhpmeventh_val[evt_index] =3D - (new_val & wr_mask) | (env->mhpmeventh_val[evt_index] & ~wr_ma= sk); - mhpmevth_val =3D env->mhpmeventh_val[evt_index]; - mhpmevt_val =3D mhpmevt_val | (mhpmevth_val << 32); - riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + write_mhpmeventh(env, ctr_idx - 3 + CSR_MHPMEVENT3H, new_val, 0); } else { return -EINVAL; } @@ -1514,21 +1490,18 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int c= fg_index, target_ulong *val, target_ulong new_val, target_ulong wr_mask) { switch (cfg_index) { - case 0: /* CYCLECFG */ + case HPM_MCYCLE_IDX: if (wr_mask) { - wr_mask &=3D ~MCYCLECFG_BIT_MINH; - env->mcyclecfg =3D (new_val & wr_mask) | (env->mcyclecfg & ~wr= _mask); + write_mcyclecfg(env, CSR_MCYCLE, new_val, 0); } else { - *val =3D env->mcyclecfg &=3D ~MHPMEVENTH_BIT_MINH; + read_mcyclecfg(env, CSR_MCYCLE, val); } break; - case 2: /* INSTRETCFG */ + case HPM_MINSTRET_IDX: if (wr_mask) { - wr_mask &=3D ~MINSTRETCFG_BIT_MINH; - env->minstretcfg =3D (new_val & wr_mask) | - (env->minstretcfg & ~wr_mask); + write_minstretcfg(env, CSR_MINSTRET, new_val, 0); } else { - *val =3D env->minstretcfg &=3D ~MHPMEVENTH_BIT_MINH; + read_minstretcfg(env, CSR_MINSTRET, val); } break; default: @@ -1540,28 +1513,19 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int c= fg_index, target_ulong *val, static int rmw_cd_ctr_cfgh(CPURISCVState *env, int cfg_index, target_ulong= *val, target_ulong new_val, target_ulong wr_mask) { - - if (riscv_cpu_mxl(env) !=3D MXL_RV32) { - return RISCV_EXCP_ILLEGAL_INST; - } - switch (cfg_index) { - case 0: /* CYCLECFGH */ + case HPM_MCYCLE_IDX: if (wr_mask) { - wr_mask &=3D ~MCYCLECFGH_BIT_MINH; - env->mcyclecfgh =3D (new_val & wr_mask) | - (env->mcyclecfgh & ~wr_mask); + write_mcyclecfgh(env, CSR_MCYCLEH, new_val, 0); } else { - *val =3D env->mcyclecfgh; + read_mcyclecfgh(env, CSR_MCYCLEH, val); } break; - case 2: /* INSTRETCFGH */ + case HPM_MINSTRET_IDX: if (wr_mask) { - wr_mask &=3D ~MINSTRETCFGH_BIT_MINH; - env->minstretcfgh =3D (new_val & wr_mask) | - (env->minstretcfgh & ~wr_mask); + write_minstretcfgh(env, CSR_MINSTRETH, new_val, 0); } else { - *val =3D env->minstretcfgh; + read_minstretcfgh(env, CSR_MINSTRETH, val); } break; default: --=20 2.51.0 From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082875; cv=none; d=zohomail.com; s=zohoarc; b=MlZT4qOodQr2ZwYL852Cxf6bfHdClylTugQfnZKcMHnueEKn0f9x6wRNlB7sAzAb5Q60EP/TbPDhh35df7RShzZyzfwOn1AJFVAvfNPs4hhYhe6bYJfiO4Hx5Yyygs4mLvTX0XutX7AURrvQOPnHsn+amtTA8z61uVtlMu5SOHM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082875; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Fz6/yRoKmyA4y96hfLNLzvlBPFCau47uJa3XYkJmMi8=; b=DRvN8gGM4042IouWJgXT8ucOwoZe7YYjtR9LLzUcDpouQiNQqNOGFHt++eS6Laru0bqZospgtQeKbLWAGZNmRvSx6jy2QFmuH9qXX/+k2wGF53rBWScOXqh1SmbPXxSxD8l8v/G8PK5xp6kyKVgnwQwenCzMxSkXHahNGZNkPzc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1766082875559224.371490312648; Thu, 18 Dec 2025 10:34:35 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo7-0003x7-Qy; Thu, 18 Dec 2025 13:32:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWIn1-0003nS-68 for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:51 -0500 Received: from mail-lf1-x12e.google.com ([2a00:1450:4864:20::12e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWImy-0007Le-EF for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:50 -0500 Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-59a10df8027so1218191e87.0 for ; Thu, 18 Dec 2025 10:31:48 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082706; x=1766687506; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Fz6/yRoKmyA4y96hfLNLzvlBPFCau47uJa3XYkJmMi8=; b=VtPvLXMJY3wGmCX2eateJS+ZyIhmPgNVCPe/uwhSXBFMruMNPSxw94dli+GUKVsHYp xh4YfRah8t4vYwLZUd8fgFSi151jE8n/bUKoW9FWfg4ceGz3E2FgzQriH/w9hQaQL4bN VoBg8jAkSDAgHL/k8cLfprtkYTF2eDKta5rHaWqaXBsEEnlLXRps1l3DWIu42smUazuh qOGKPqsEjdbCD0R0j+KpHdBt6vqS9Hpm3s3/jBgEl0W5hJ79wctimKI6hX4bmXwsVhn3 ovNLtDhYKYPI/4Wd/6DCvuYWT88iqvV2mp5xXVO2wcWtG2i3NUeYao0NNvfujUspgxWK c9QA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082706; x=1766687506; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Fz6/yRoKmyA4y96hfLNLzvlBPFCau47uJa3XYkJmMi8=; b=royWarVpyrn0KAzGpnyfYQeypjIeJoewRSKcFqpckMLaMoQkv9IxUiyTJUvp7Qeo3U 7WoyaIxu+t2OIZRdvtEUJfFF6NEDO75N/UCCEFX3tPe6/yCc15Wq+/T1Oh+iGZ4a5J3K TDI4gfHNVSWUTD6rPOJcvkC3DfIu+KPpRCn7f/MGunMzti990dBKYYZ9WfH5fGV2WtSl QGQJiIkac6wpuRRJ9ml8Fapm4Vn29Vmf8z1992ohfB24CBb2uoDVGrVSVQsWyxkaqeSI NNAiuHRsyWDnKIcmkOza9hbsPAhUM7EA5o5z44+atQZ0j/tRZCmE0haI4bIwctYbkqZ1 MiYA== X-Gm-Message-State: AOJu0YzwFjk2Yhw1le52WmCDIBcG8x0HYNMfTCS2fy0gOE6K69kiMpry 9n2A9FX4NeYvb4wRJ2iLXmpEtvSEXeXafDT2FvrafyVMB4QTfDoHwSLjsb02AFPb X-Gm-Gg: AY/fxX5QU28zf8S9MocugyZSCAC1nEFOLohJHVbpY2LKbvUUislHsK+YmowKMdpddrU NRWnLRaNS8JlOoeki86TwLdXgGOx2TzusAD0PcZtx6/3F6iODsXRdsMVcWNWCHp5VcODzjzDB7D +XZRj6Mwjm4sdBMcMNJLvnTBfMDE0Her7VhIcpYh7qPOixTrquF5dmda+df2yhILBol3qVU2HkA aibO5+fk8iybSswFpDJVKTMGKPtNngMeoX2tE5yKpjG4n/ahbsmkwQCTsBLZFUvhslrXe0sOjA8 o8RtQr/+x24lxhLrjPsNfL99oZ+7MGgESJ/32VAG0XUxTOR9vcu8UmkTcMeqflpsQM1/5kGzfJr rBYlE3we8n0ZfFNrBY4d+XnepMeiQJy35e6BQSj1Qh4ee/C+CLaZxxHaIOwFOi1R7G+ef1AZywR pL5qKURnNGtHLS X-Google-Smtp-Source: AGHT+IHEqFEpp06qf9xlk6BJPLvkyTjKlUCY7QBfpUnETc8xFLLng4gDGoFLnkq/9zM2q94dEmw11Q== X-Received: by 2002:a05:6512:3d1f:b0:594:3340:1b63 with SMTP id 2adb3069b0e04-59a17d76d7bmr197909e87.49.1766082706092; Thu, 18 Dec 2025 10:31:46 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 3/6] target/riscv: Get rid of hardcoded SBI events. Date: Thu, 18 Dec 2025 21:31:18 +0300 Message-ID: <20251218183122.408690-4-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::12e; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x12e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:44 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082877785158500 Content-Type: text/plain; charset="utf-8" SBI events are not a part of RISC-V specification and should not be hardcoded right in QEMU. It's up to vendor to implement them. Also, we can get rid of event->ctr mapping, as it is used only for SBI event handling. Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- target/riscv/cpu.h | 15 --- target/riscv/cpu_helper.c | 23 ---- target/riscv/csr.c | 18 +-- target/riscv/pmu.c | 240 ++------------------------------------ target/riscv/pmu.h | 7 -- 5 files changed, 16 insertions(+), 287 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 36e7f10037..8ab5fa0afb 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -550,8 +550,6 @@ struct ArchCPU { QEMUTimer *pmu_timer; /* A bitmask of Available programmable counters */ uint32_t pmu_avail_ctrs; - /* Mapping of events to counters */ - GHashTable *pmu_event_ctr_map; const GPtrArray *decoders; }; =20 @@ -925,19 +923,6 @@ enum { CSR_TABLE_SIZE =3D 0x1000 }; =20 -/* - * The event id are encoded based on the encoding specified in the - * SBI specification v0.3 - */ - -enum riscv_pmu_event_idx { - RISCV_PMU_EVENT_HW_CPU_CYCLES =3D 0x01, - RISCV_PMU_EVENT_HW_INSTRUCTIONS =3D 0x02, - RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS =3D 0x10019, - RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS =3D 0x1001B, - RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS =3D 0x10021, -}; - /* used by tcg/tcg-cpu.c*/ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en); bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset); diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index c4fb68b5de..b3780cf8a8 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1736,28 +1736,6 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vad= dr addr, cpu_loop_exit_restore(cs, retaddr); } =20 - -static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType access_type) -{ - enum riscv_pmu_event_idx pmu_event_type; - - switch (access_type) { - case MMU_INST_FETCH: - pmu_event_type =3D RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS; - break; - case MMU_DATA_LOAD: - pmu_event_type =3D RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS; - break; - case MMU_DATA_STORE: - pmu_event_type =3D RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS; - break; - default: - return; - } - - riscv_pmu_incr_ctr(cpu, pmu_event_type); -} - bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) @@ -1781,7 +1759,6 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, = int size, qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n", __func__, address, access_type, mmu_idx); =20 - pmu_tlb_fill_incr_ctr(cpu, access_type); if (two_stage_lookup) { /* Two stage lookup */ ret =3D get_physical_address(env, &pa, &prot, address, diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 81475ec9a3..fb052725fe 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1188,8 +1188,6 @@ static RISCVException write_mhpmevent(CPURISCVState *= env, int csrno, env->mhpmevent_val[ctr_idx] =3D mhpmevt_val; } =20 - riscv_pmu_update_event_map(env, mhpmevt_val, ctr_idx); - return RISCV_EXCP_NONE; } =20 @@ -1223,8 +1221,6 @@ static RISCVException write_mhpmeventh(CPURISCVState = *env, int csrno, mhpmevt_val =3D mhpmevt_val | (mhpmevth_val << 32); env->mhpmeventh_val[ctr_idx] =3D mhpmevth_val; =20 - riscv_pmu_update_event_map(env, mhpmevt_val, ctr_idx); - return RISCV_EXCP_NONE; } =20 @@ -1232,7 +1228,7 @@ static target_ulong riscv_pmu_ctr_get_fixed_counters_= val(CPURISCVState *env, int counter_idx, bool upper_half) { - int inst =3D riscv_pmu_ctr_monitor_instructions(env, counter_idx); + int inst =3D (counter_idx =3D=3D HPM_MINSTRET_IDX); uint64_t *counter_arr_virt =3D env->pmu_fixed_ctrs[inst].counter_virt; uint64_t *counter_arr =3D env->pmu_fixed_ctrs[inst].counter; target_ulong result =3D 0; @@ -1303,8 +1299,7 @@ static RISCVException riscv_pmu_write_ctr(CPURISCVSta= te *env, target_ulong val, =20 counter->mhpmcounter_val =3D val; if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && - (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { + (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX)= ) { counter->mhpmcounter_prev =3D riscv_pmu_ctr_get_fixed_counters_val= (env, ctr_idx, f= alse); if (ctr_idx > 2) { @@ -1332,8 +1327,7 @@ static RISCVException riscv_pmu_write_ctrh(CPURISCVSt= ate *env, target_ulong val, counter->mhpmcounterh_val =3D val; mhpmctr_val =3D mhpmctr_val | (mhpmctrh_val << 32); if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && - (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { + (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX)= ) { counter->mhpmcounterh_prev =3D riscv_pmu_ctr_get_fixed_counters_va= l(env, ctr_idx, = true); if (ctr_idx > 2) { @@ -1384,8 +1378,7 @@ RISCVException riscv_pmu_read_ctr(CPURISCVState *env,= target_ulong *val, * The kernel computes the perf delta by subtracting the current value= from * the value it initialized previously (ctr_val). */ - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX) { *val =3D riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, upper_= half) - ctr_prev + ctr_val; } else { @@ -2955,8 +2948,7 @@ static RISCVException write_mcountinhibit(CPURISCVSta= te *env, int csrno, /* Check if any other counter is also monitoring cycles/instructions */ for (cidx =3D 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { if (!(updated_ctrs & BIT(cidx)) || - (!riscv_pmu_ctr_monitor_cycles(env, cidx) && - !riscv_pmu_ctr_monitor_instructions(env, cidx))) { + (cidx !=3D HPM_MCYCLE_IDX && cidx !=3D HPM_MINSTRET_IDX)) { continue; } =20 diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index b983eadd83..c503fffde1 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -101,82 +101,6 @@ static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, u= int32_t ctr_idx) } } =20 -static int riscv_pmu_incr_ctr_rv32(RISCVCPU *cpu, uint32_t ctr_idx) -{ - CPURISCVState *env =3D &cpu->env; - target_ulong max_val =3D UINT32_MAX; - PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; - bool virt_on =3D env->virt_enabled; - - /* Privilege mode filtering */ - if ((env->priv =3D=3D PRV_M && - (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_MINH)) || - (env->priv =3D=3D PRV_S && virt_on && - (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VSINH)) || - (env->priv =3D=3D PRV_U && virt_on && - (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VUINH)) || - (env->priv =3D=3D PRV_S && !virt_on && - (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_SINH)) || - (env->priv =3D=3D PRV_U && !virt_on && - (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_UINH))) { - return 0; - } - - /* Handle the overflow scenario */ - if (counter->mhpmcounter_val =3D=3D max_val) { - if (counter->mhpmcounterh_val =3D=3D max_val) { - counter->mhpmcounter_val =3D 0; - counter->mhpmcounterh_val =3D 0; - /* Generate interrupt only if OF bit is clear */ - if (!(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_OF)) { - env->mhpmeventh_val[ctr_idx] |=3D MHPMEVENTH_BIT_OF; - riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1)); - } - } else { - counter->mhpmcounterh_val++; - } - } else { - counter->mhpmcounter_val++; - } - - return 0; -} - -static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx) -{ - CPURISCVState *env =3D &cpu->env; - PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; - uint64_t max_val =3D UINT64_MAX; - bool virt_on =3D env->virt_enabled; - - /* Privilege mode filtering */ - if ((env->priv =3D=3D PRV_M && - (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_MINH)) || - (env->priv =3D=3D PRV_S && virt_on && - (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VSINH)) || - (env->priv =3D=3D PRV_U && virt_on && - (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VUINH)) || - (env->priv =3D=3D PRV_S && !virt_on && - (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_SINH)) || - (env->priv =3D=3D PRV_U && !virt_on && - (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_UINH))) { - return 0; - } - - /* Handle the overflow scenario */ - if (counter->mhpmcounter_val =3D=3D max_val) { - counter->mhpmcounter_val =3D 0; - /* Generate interrupt only if OF bit is clear */ - if (!(env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_OF)) { - env->mhpmevent_val[ctr_idx] |=3D MHPMEVENT_BIT_OF; - riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1)); - } - } else { - counter->mhpmcounter_val++; - } - return 0; -} - /* * Information needed to update counters: * new_priv, new_virt: To correctly save starting snapshot for the newly @@ -272,97 +196,6 @@ void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, t= arget_ulong newpriv, riscv_pmu_icount_update_priv(env, newpriv, new_virt); } =20 -int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) -{ - uint32_t ctr_idx; - int ret; - CPURISCVState *env =3D &cpu->env; - gpointer value; - - if (!cpu->cfg.pmu_mask) { - return 0; - } - value =3D g_hash_table_lookup(cpu->pmu_event_ctr_map, - GUINT_TO_POINTER(event_idx)); - if (!value) { - return -1; - } - - ctr_idx =3D GPOINTER_TO_UINT(value); - if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { - return -1; - } - - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - ret =3D riscv_pmu_incr_ctr_rv32(cpu, ctr_idx); - } else { - ret =3D riscv_pmu_incr_ctr_rv64(cpu, ctr_idx); - } - - return ret; -} - -bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, - uint32_t target_ctr) -{ - RISCVCPU *cpu; - uint32_t event_idx; - uint32_t ctr_idx; - - /* Fixed instret counter */ - if (target_ctr =3D=3D 2) { - return true; - } - - cpu =3D env_archcpu(env); - if (!cpu->pmu_event_ctr_map) { - return false; - } - - event_idx =3D RISCV_PMU_EVENT_HW_INSTRUCTIONS; - ctr_idx =3D GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_ma= p, - GUINT_TO_POINTER(event_idx))); - if (!ctr_idx) { - return false; - } - - return target_ctr =3D=3D ctr_idx ? true : false; -} - -bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr) -{ - RISCVCPU *cpu; - uint32_t event_idx; - uint32_t ctr_idx; - - /* Fixed mcycle counter */ - if (target_ctr =3D=3D 0) { - return true; - } - - cpu =3D env_archcpu(env); - if (!cpu->pmu_event_ctr_map) { - return false; - } - - event_idx =3D RISCV_PMU_EVENT_HW_CPU_CYCLES; - ctr_idx =3D GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_ma= p, - GUINT_TO_POINTER(event_idx))); - - /* Counter zero is not used for event_ctr_map */ - if (!ctr_idx) { - return false; - } - - return (target_ctr =3D=3D ctr_idx) ? true : false; -} - -static gboolean pmu_remove_event_map(gpointer key, gpointer value, - gpointer udata) -{ - return (GPOINTER_TO_UINT(value) =3D=3D GPOINTER_TO_UINT(udata)) ? true= : false; -} - static int64_t pmu_icount_ticks_to_ns(int64_t value) { int64_t ret =3D 0; @@ -376,50 +209,6 @@ static int64_t pmu_icount_ticks_to_ns(int64_t value) return ret; } =20 -int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, - uint32_t ctr_idx) -{ - uint32_t event_idx; - RISCVCPU *cpu =3D env_archcpu(env); - - if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->pmu_event_ctr_map)= { - return -1; - } - - /* - * Expected mhpmevent value is zero for reset case. Remove the current - * mapping. - */ - if (!(value & MHPMEVENT_IDX_MASK)) { - g_hash_table_foreach_remove(cpu->pmu_event_ctr_map, - pmu_remove_event_map, - GUINT_TO_POINTER(ctr_idx)); - return 0; - } - - event_idx =3D value & MHPMEVENT_IDX_MASK; - if (g_hash_table_lookup(cpu->pmu_event_ctr_map, - GUINT_TO_POINTER(event_idx))) { - return 0; - } - - switch (event_idx) { - case RISCV_PMU_EVENT_HW_CPU_CYCLES: - case RISCV_PMU_EVENT_HW_INSTRUCTIONS: - case RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS: - case RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS: - case RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS: - break; - default: - /* We don't support any raw events right now */ - return -1; - } - g_hash_table_insert(cpu->pmu_event_ctr_map, GUINT_TO_POINTER(event_idx= ), - GUINT_TO_POINTER(ctr_idx)); - - return 0; -} - static bool pmu_hpmevent_is_of_set(CPURISCVState *env, uint32_t ctr_idx) { target_ulong mhpmevent_val; @@ -457,23 +246,19 @@ static bool pmu_hpmevent_set_of_if_clear(CPURISCVStat= e *env, uint32_t ctr_idx) return false; } =20 -static void pmu_timer_trigger_irq(RISCVCPU *cpu, - enum riscv_pmu_event_idx evt_idx) +static void pmu_timer_trigger_irq(RISCVCPU *cpu, uint32_t ctr_idx) { - uint32_t ctr_idx; CPURISCVState *env =3D &cpu->env; PMUCTRState *counter; int64_t irq_trigger_at; uint64_t curr_ctr_val, curr_ctrh_val; uint64_t ctr_val; =20 - if (evt_idx !=3D RISCV_PMU_EVENT_HW_CPU_CYCLES && - evt_idx !=3D RISCV_PMU_EVENT_HW_INSTRUCTIONS) { + if (ctr_idx !=3D HPM_MINSTRET_IDX && + ctr_idx !=3D HPM_MCYCLE_IDX) { return; } =20 - ctr_idx =3D GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_ma= p, - GUINT_TO_POINTER(evt_idx))); if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { return; } @@ -523,10 +308,13 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, void riscv_pmu_timer_cb(void *priv) { RISCVCPU *cpu =3D priv; + uint32_t ctr_idx; =20 - /* Timer event was triggered only for these events */ - pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_CPU_CYCLES); - pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_INSTRUCTIONS); + for (ctr_idx =3D 0; ctr_idx < RV_MAX_MHPMCOUNTERS; ctr_idx++) { + if (riscv_pmu_counter_valid(cpu, ctr_idx)) { + pmu_timer_trigger_irq(cpu, ctr_idx); + } + } } =20 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr= _idx) @@ -557,8 +345,8 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t = value, uint32_t ctr_idx) overflow_left =3D overflow_delta - INT64_MAX; } =20 - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (ctr_idx =3D=3D HPM_MCYCLE_IDX || + ctr_idx =3D=3D HPM_MINSTRET_IDX) { overflow_ns =3D pmu_icount_ticks_to_ns((int64_t)overflow_delta); overflow_left =3D pmu_icount_ticks_to_ns(overflow_left) ; } else { @@ -592,12 +380,6 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) return; } =20 - cpu->pmu_event_ctr_map =3D g_hash_table_new(g_direct_hash, g_direct_eq= ual); - if (!cpu->pmu_event_ctr_map) { - error_setg(errp, "Unable to allocate PMU event hash table"); - return; - } - cpu->pmu_avail_ctrs =3D cpu->cfg.pmu_mask; } =20 diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 8f019bea9f..97b167d8f2 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -22,15 +22,8 @@ #include "cpu.h" #include "qapi/error.h" =20 -bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, - uint32_t target_ctr); -bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, - uint32_t target_ctr); void riscv_pmu_timer_cb(void *priv); void riscv_pmu_init(RISCVCPU *cpu, Error **errp); -int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, - uint32_t ctr_idx); -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= ); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); --=20 2.51.0 From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082812; cv=none; d=zohomail.com; s=zohoarc; b=L5+sTlE8ns82IKt9v11XU+2UZF8Bkxvtx4FNcktinEL/oV8u+fcvWwWKhLcXEZs97LWzDP2ho4HULRnUOLsMSyQ4wWbHpxKP94fGhmdixMiLJ+Hc/IUsk5/fCEKmV8Gf36u2FeCZVhe1TGgJlK/o8TKh+ndKz+hujXFspeZEP+I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082812; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=k9GTjMFaV7N8o4SrcAPpuEaFHzKRMNAJ0In4YQ733Ls=; b=Nv4pnae/Gv93b+DzqfDNAmE0u3lb+DXHwaDqVaeUDheFRMkm3KfR4AsRF3rqMfpnRiM/SiAOPmPhw6mtmq0v/NuZ9OUpYSaoeAt4DQSxqzRedQkP6Z7DspXD5JD3nafMlh0uaHoZbQkNBCqJMLVv/iidwH0KsoBYFLGz+/idpkE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1766082812859687.2449272776784; Thu, 18 Dec 2025 10:33:32 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo8-0003x8-9C; Thu, 18 Dec 2025 13:33:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWIn4-0003oA-1Y for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:54 -0500 Received: from mail-lf1-x12d.google.com ([2a00:1450:4864:20::12d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWImz-0007M3-Ta for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:53 -0500 Received: by mail-lf1-x12d.google.com with SMTP id 2adb3069b0e04-59431f57bf6so1018721e87.3 for ; Thu, 18 Dec 2025 10:31:49 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082708; x=1766687508; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=k9GTjMFaV7N8o4SrcAPpuEaFHzKRMNAJ0In4YQ733Ls=; b=Bc9I8WOi/lBR2SKfy4PWM1aEjcXQtxphH9Php1Qq2myuTXyUiqC7Nk54uzLefUCm5a yWfP1iRj10EckRUFwOnI0hfwKzHQGyQa056R+6QPfE8YdsM3Q3JO7c9xw6BGTZ43UfKp rLwWeNwNIqbUnK9BW1tXQHq+ClNV3IP0OjWBzr91b23k9y8z3Ht6BLhNEVZFu2wSxiQS 21gwRLx3wofpCFm0wGDktgayCO6Flkvvvvxt8Frwu1JNyiTpLcarUzJ/U8zXLWcGkpAf fQUKGge7pwp7XCvPoSY52Mf9wZkOD39YrFa3xYVRTIG0dj514ZIAMXc1gfaBmJOpve+z FwFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082708; x=1766687508; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=k9GTjMFaV7N8o4SrcAPpuEaFHzKRMNAJ0In4YQ733Ls=; b=VQ7UV1SABibMe2gcRzWBeQEZErIdWPIypfxR4HpUwHnlSLcJcQwSUfDR2d2Z14FHDr vVWezfnWLrYqQT4FJ1BaE5YXQ1AVUHBcZk9oIwiJ1u0NioAIUnXVOzFkt0rwNPzXpEzZ rdigF/ydSlOkzj8GTaGTUPc6fjXhfS8JcpnJj4VBs1V4c8PM/h4g0HgH7OVUKlWwY9m3 zIFfF32pHKlU2Etv4rLmLSjpzkL7Vub7jOny43NYmY+nXGc1a7olvQAwqZKujcGmU0tJ mqQnFb6hDt44kwKlqwl7AwKAf2m42jApdexGksnWZjMbvs/JFxa5RBPfv+aQIw9Armxj Na8w== X-Gm-Message-State: AOJu0YxvSX0UlJdyaVEY9z8mz2TOdzMWQxKNM1FVYjQgiyvoHH20U70m yKmSoSnU8gO3QKvflFVWG+l5J2Q2rOBAMhjgMEKPSxgK3KMBZKO6OgAXplUcjTiR X-Gm-Gg: AY/fxX7PX4rW+dbLSIaVStqComwSq1j3hMyxLxVU/qMvCqqytUZ6rsG+7Z030VU82pz blefeldsOwEL6e3jugAYffThIwYIEy8svN/UMJZgFW+qxQzB8OuhxIbGa9qyjwpylJHWffXAwK4 IJYQrG0hQI2eJeL/D+5RF04FpeTUk04bQ2VqhqPRsXg+QdGOlS8z/Y0gySXf/TsYk69n61ZA98X rtIJfjN+IlVYNbwGLxukzEL/KxPVyT17apIu+nvd7YxckxHw2LMtSHbvsxAOFzd09z87ESi+ZBI OC9dsvF2P96FkOxiMI6yfBPlTD7po5dYA1gDxZlslL5m+RN1m17sN324UYQaTYUoKY9av4Zh1nl YC7jsn0JJqaSNrc6HjWjPpP64fVu9VzuM4vOA0ixQPm1BHuJy530TER6nl3xHP9YCg4bbZ6BNxB VqWKnhrOlVDIR8 X-Google-Smtp-Source: AGHT+IH/Xkvfkl19cXASYaHkmb/CplFOkafM7L+4S4yJ7pVmEZ+0QLwwH6hjfRpo1zR72TP7ALqy1w== X-Received: by 2002:a05:6512:220d:b0:59a:123e:69ac with SMTP id 2adb3069b0e04-59a17d43b8fmr178736e87.27.1766082707364; Thu, 18 Dec 2025 10:31:47 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 4/6] target/riscv: Rearrange custom hpm counter api Date: Thu, 18 Dec 2025 21:31:19 +0300 Message-ID: <20251218183122.408690-5-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::12d; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x12d.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:45 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082813472158500 Content-Type: text/plain; charset="utf-8" Current counter api lacks extendability. Vendor may want to implement some custom logic for the events To do that, vendor must hardcode it right inside the general methods. So if there are two different vendors with their own events, they would write their code right beside each other. The counter api was unified to make it extendable, letting vendor fully customize the logic. The counter is now described with 2 actions: - read: returns the current value of the counter - write: sets the value of the counter All the logic for the counters, including inhibiting, filtering, etc, is written in terms of read/write and completely determined by the vendor. Vendor is up to choose how to use prev & val variables. (including totally ignoring them), so we can't rely on any values in it. Also 64bit variables are now used for prev & val, avoiding manual handling of 32bit overflows and making code a bit more clean & simple. Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- target/riscv/cpu.h | 81 ++++++-- target/riscv/cpu_helper.c | 11 +- target/riscv/csr.c | 337 ++++++++++++--------------------- target/riscv/machine.c | 7 +- target/riscv/pmu.c | 383 ++++++++++++++++++++++---------------- target/riscv/pmu.h | 17 +- 6 files changed, 431 insertions(+), 405 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8ab5fa0afb..d8d20559d1 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -194,28 +194,44 @@ FIELD(VTYPE, VMA, 7, 1) FIELD(VTYPE, VEDIV, 8, 2) FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11) =20 +/* + * Let the counter count some event E. + * + * Lets call a `raw` value of the counter some arbitrary value, + * which increases as event E happens. + * Lets also assume the `raw` value is read-only and can't be changed by u= s. + * + * Now we want to initialize the counter with some value X. + * For that lets add a few more variables: + * `val` would contain our initial value X, + * `prev` would contain the `raw` value of the counter at the moment of th= e write. + * `(raw - prev)` is `delta` -- the number of events, + * which happened since the last write. + * + * So the current value of the counter can be calculated as + * `(delta + val) =3D=3D (raw - prev + val)`. + * + * Each time you write X to the counter, just do: + * `val =3D X; prev =3D raw` + * We can also avoid manual usage of `raw` in code by doing: + * `val =3D X; prev +=3D delta` + * + * We also want to inhibit our counter sometimes. + * If the counter is inhibited, just assume `delta =3D=3D 0`. + * + * Text above describes the way builtin counters (mcycle, minstret) + * work. However, when implementing vendor events, you are + * free to use `prev` and `val` registers whatever you want. + */ typedef struct PMUCTRState { /* Current value of a counter */ - target_ulong mhpmcounter_val; - /* Current value of a counter in RV32 */ - target_ulong mhpmcounterh_val; + uint64_t mhpmcounter_val; /* Snapshot values of counter */ - target_ulong mhpmcounter_prev; - /* Snapshort value of a counter in RV32 */ - target_ulong mhpmcounterh_prev; - /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigge= r */ - target_ulong irq_overflow_left; + uint64_t mhpmcounter_prev; + /* Is counter overflowed */ + bool overflowed; } PMUCTRState; =20 -typedef struct PMUFixedCtrState { - /* Track cycle and icount for each privilege mode */ - uint64_t counter[4]; - uint64_t counter_prev[4]; - /* Track cycle and icount for each privilege mode when V =3D 1*/ - uint64_t counter_virt[2]; - uint64_t counter_virt_prev[2]; -} PMUFixedCtrState; - struct CPUArchState { target_ulong gpr[32]; target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */ @@ -434,8 +450,6 @@ struct CPUArchState { /* PMU event selector configured values for RV32 */ target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS]; =20 - PMUFixedCtrState pmu_fixed_ctrs[2]; - target_ulong sscratch; target_ulong mscratch; =20 @@ -464,6 +478,35 @@ struct CPUArchState { uint64_t (*rdtime_fn)(void *); void *rdtime_fn_arg; =20 + /*machine specific pmu callback */ + + /* + * Returns uint64 value of the counter `ctr_idx`. + * + * Should also set `PMUCTRState::overflowed`, + * if the counter overflows. + * + * See `riscv_pmu_ctr_read_general` for the example. + */ + RISCVException (*pmu_ctr_read)(CPURISCVState *env, uint32_t ctr_idx, + uint64_t *value); + /* + * Writes value to the counter `ctr_idx`. + * + * Guarantied to be called for vendor events, when: + * - inhibiting/uninhibiting + * - switching cpu mode (to support filtering) + * - changing mhpmevent/mhpmeventh + * + * See `riscv_pmu_ctr_write_general` for the example. + */ + RISCVException (*pmu_ctr_write)(CPURISCVState *env, uint32_t ctr_idx, + uint64_t value); + /* + * Returns true, if the event is supported by vendor. + */ + bool (*pmu_vendor_support)(CPURISCVState *env, uint32_t ctr_idx); + /* machine specific AIA ireg read-modify-write callback */ #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \ ((((__xlen) & 0xff) << 24) | \ diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index b3780cf8a8..2703279847 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1036,10 +1036,15 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_= ulong newpriv, bool virt_en) if (icount_enabled()) { riscv_itrigger_update_priv(env); } - - riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en); } =20 + /* + * Preserve pmu ctr values and + * restore them after the mode change. + */ + riscv_pmu_preserved_ctrs_t preserved_ctrs; + riscv_pmu_preserve_ctrs(env, preserved_ctrs); + /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv =3D newpriv; env->xl =3D cpu_recompute_xl(env); @@ -1075,6 +1080,8 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ul= ong newpriv, bool virt_en) riscv_cpu_update_mip(env, 0, 0); } } + + riscv_pmu_restore_ctrs(env, preserved_ctrs); } =20 /* diff --git a/target/riscv/csr.c b/target/riscv/csr.c index fb052725fe..72715d9b15 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1060,6 +1060,14 @@ static RISCVException write_mcyclecfg(CPURISCVState = *env, int csrno, target_ulong val, uintptr_t ra) { uint64_t inh_avail_mask; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { env->mcyclecfg =3D val; @@ -1075,7 +1083,9 @@ static RISCVException write_mcyclecfg(CPURISCVState *= env, int csrno, env->mcyclecfg =3D val & inh_avail_mask; } =20 - return RISCV_EXCP_NONE; + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + + return excp; } =20 static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno, @@ -1090,6 +1100,14 @@ static RISCVException write_mcyclecfgh(CPURISCVState= *env, int csrno, { target_ulong inh_avail_mask =3D (target_ulong)(~MHPMEVENTH_FILTER_MASK= | MCYCLECFGH_BIT_MINH); + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 /* Set xINH fields if priv mode supported */ inh_avail_mask |=3D riscv_has_ext(env, RVU) ? MCYCLECFGH_BIT_UINH : 0; @@ -1100,7 +1118,10 @@ static RISCVException write_mcyclecfgh(CPURISCVState= *env, int csrno, riscv_has_ext(env, RVS)) ? MCYCLECFGH_BIT_VSINH : 0; =20 env->mcyclecfgh =3D val & inh_avail_mask; - return RISCV_EXCP_NONE; + + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + + return excp; } =20 static RISCVException read_minstretcfg(CPURISCVState *env, int csrno, @@ -1114,6 +1135,14 @@ static RISCVException write_minstretcfg(CPURISCVStat= e *env, int csrno, target_ulong val, uintptr_t ra) { uint64_t inh_avail_mask; + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { env->minstretcfg =3D val; @@ -1127,7 +1156,10 @@ static RISCVException write_minstretcfg(CPURISCVStat= e *env, int csrno, riscv_has_ext(env, RVS)) ? MINSTRETCFG_BIT_VSIN= H : 0; env->minstretcfg =3D val & inh_avail_mask; } - return RISCV_EXCP_NONE; + + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + + return excp; } =20 static RISCVException read_minstretcfgh(CPURISCVState *env, int csrno, @@ -1142,6 +1174,14 @@ static RISCVException write_minstretcfgh(CPURISCVSta= te *env, int csrno, { target_ulong inh_avail_mask =3D (target_ulong)(~MHPMEVENTH_FILTER_MASK= | MINSTRETCFGH_BIT_MINH); + uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 inh_avail_mask |=3D riscv_has_ext(env, RVU) ? MINSTRETCFGH_BIT_UINH : = 0; inh_avail_mask |=3D riscv_has_ext(env, RVS) ? MINSTRETCFGH_BIT_SINH : = 0; @@ -1151,7 +1191,10 @@ static RISCVException write_minstretcfgh(CPURISCVSta= te *env, int csrno, riscv_has_ext(env, RVS)) ? MINSTRETCFGH_BIT_VSINH := 0; =20 env->minstretcfgh =3D val & inh_avail_mask; - return RISCV_EXCP_NONE; + + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + + return excp; } =20 static RISCVException read_mhpmevent(CPURISCVState *env, int csrno, @@ -1168,14 +1211,17 @@ static RISCVException write_mhpmevent(CPURISCVState= *env, int csrno, target_ulong val, uintptr_t ra) { uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); - - uint64_t mhpmevt_val =3D val; uint64_t inh_avail_mask; + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { env->mhpmevent_val[ctr_idx] =3D val; - mhpmevt_val =3D mhpmevt_val | - ((uint64_t)env->mhpmeventh_val[ctr_idx] << 32); } else { inh_avail_mask =3D ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH; inh_avail_mask |=3D riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH := 0; @@ -1184,11 +1230,12 @@ static RISCVException write_mhpmevent(CPURISCVState= *env, int csrno, riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH = : 0; inh_avail_mask |=3D (riscv_has_ext(env, RVH) && riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH = : 0; - mhpmevt_val =3D val & inh_avail_mask; - env->mhpmevent_val[ctr_idx] =3D mhpmevt_val; + env->mhpmevent_val[ctr_idx] =3D val & inh_avail_mask; } =20 - return RISCV_EXCP_NONE; + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + + return excp; } =20 static RISCVException read_mhpmeventh(CPURISCVState *env, int csrno, @@ -1205,10 +1252,15 @@ static RISCVException write_mhpmeventh(CPURISCVStat= e *env, int csrno, target_ulong val, uintptr_t ra) { uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); - uint64_t mhpmevth_val; - uint64_t mhpmevt_val =3D env->mhpmevent_val[ctr_idx]; target_ulong inh_avail_mask =3D (target_ulong)(~MHPMEVENTH_FILTER_MASK= | MHPMEVENTH_BIT_MINH); + RISCVException excp; + uint64_t ctr_val; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } =20 inh_avail_mask |=3D riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0; inh_avail_mask |=3D riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0; @@ -1216,191 +1268,74 @@ static RISCVException write_mhpmeventh(CPURISCVSta= te *env, int csrno, riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0; inh_avail_mask |=3D (riscv_has_ext(env, RVH) && riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0; + env->mhpmeventh_val[ctr_idx] =3D val & inh_avail_mask; =20 - mhpmevth_val =3D val & inh_avail_mask; - mhpmevt_val =3D mhpmevt_val | (mhpmevth_val << 32); - env->mhpmeventh_val[ctr_idx] =3D mhpmevth_val; + excp =3D riscv_pmu_ctr_write(env, ctr_idx, ctr_val); =20 - return RISCV_EXCP_NONE; -} - -static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *en= v, - int counter_idx, - bool upper_half) -{ - int inst =3D (counter_idx =3D=3D HPM_MINSTRET_IDX); - uint64_t *counter_arr_virt =3D env->pmu_fixed_ctrs[inst].counter_virt; - uint64_t *counter_arr =3D env->pmu_fixed_ctrs[inst].counter; - target_ulong result =3D 0; - uint64_t curr_val =3D 0; - uint64_t cfg_val =3D 0; - - if (counter_idx =3D=3D 0) { - cfg_val =3D upper_half ? ((uint64_t)env->mcyclecfgh << 32) : - env->mcyclecfg; - } else if (counter_idx =3D=3D 2) { - cfg_val =3D upper_half ? ((uint64_t)env->minstretcfgh << 32) : - env->minstretcfg; - } else { - cfg_val =3D upper_half ? - ((uint64_t)env->mhpmeventh_val[counter_idx] << 32) : - env->mhpmevent_val[counter_idx]; - cfg_val &=3D MHPMEVENT_FILTER_MASK; - } - - if (!cfg_val) { - if (icount_enabled()) { - curr_val =3D inst ? icount_get_raw() : icount_get(); - } else { - curr_val =3D cpu_get_host_ticks(); - } - - goto done; - } - - /* Update counter before reading. */ - riscv_pmu_update_fixed_ctrs(env, env->priv, env->virt_enabled); - - if (!(cfg_val & MCYCLECFG_BIT_MINH)) { - curr_val +=3D counter_arr[PRV_M]; - } - - if (!(cfg_val & MCYCLECFG_BIT_SINH)) { - curr_val +=3D counter_arr[PRV_S]; - } - - if (!(cfg_val & MCYCLECFG_BIT_UINH)) { - curr_val +=3D counter_arr[PRV_U]; - } - - if (!(cfg_val & MCYCLECFG_BIT_VSINH)) { - curr_val +=3D counter_arr_virt[PRV_S]; - } - - if (!(cfg_val & MCYCLECFG_BIT_VUINH)) { - curr_val +=3D counter_arr_virt[PRV_U]; - } - -done: - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - result =3D upper_half ? curr_val >> 32 : curr_val; - } else { - result =3D curr_val; - } - - return result; -} - -static RISCVException riscv_pmu_write_ctr(CPURISCVState *env, target_ulong= val, - uint32_t ctr_idx) -{ - PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; - uint64_t mhpmctr_val =3D val; - - counter->mhpmcounter_val =3D val; - if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && - (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX)= ) { - counter->mhpmcounter_prev =3D riscv_pmu_ctr_get_fixed_counters_val= (env, - ctr_idx, f= alse); - if (ctr_idx > 2) { - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - mhpmctr_val =3D mhpmctr_val | - ((uint64_t)counter->mhpmcounterh_val << 32); - } - riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx); - } - } else { - /* Other counters can keep incrementing from the given value */ - counter->mhpmcounter_prev =3D val; - } - - return RISCV_EXCP_NONE; -} - -static RISCVException riscv_pmu_write_ctrh(CPURISCVState *env, target_ulon= g val, - uint32_t ctr_idx) -{ - PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; - uint64_t mhpmctr_val =3D counter->mhpmcounter_val; - uint64_t mhpmctrh_val =3D val; - - counter->mhpmcounterh_val =3D val; - mhpmctr_val =3D mhpmctr_val | (mhpmctrh_val << 32); - if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && - (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX)= ) { - counter->mhpmcounterh_prev =3D riscv_pmu_ctr_get_fixed_counters_va= l(env, - ctr_idx, = true); - if (ctr_idx > 2) { - riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx); - } - } else { - counter->mhpmcounterh_prev =3D val; - } - - return RISCV_EXCP_NONE; + return excp; } =20 static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + uint64_t ctr_val; + RISCVException excp; =20 - return riscv_pmu_write_ctr(env, val, ctr_idx); + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } + + ctr_val =3D deposit64(ctr_val, 0, 32, val); + return riscv_pmu_ctr_write(env, ctr_idx, ctr_val); + } else { + return riscv_pmu_ctr_write(env, ctr_idx, val); + } } =20 static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); + uint64_t ctr_val; + RISCVException excp; =20 - return riscv_pmu_write_ctrh(env, val, ctr_idx); -} - -RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, - bool upper_half, uint32_t ctr_idx) -{ - PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; - target_ulong ctr_prev =3D upper_half ? counter->mhpmcounterh_prev : - counter->mhpmcounter_prev; - target_ulong ctr_val =3D upper_half ? counter->mhpmcounterh_val : - counter->mhpmcounter_val; - - if (get_field(env->mcountinhibit, BIT(ctr_idx))) { - /* - * Counter should not increment if inhibit bit is set. Just return= the - * current counter value. - */ - *val =3D ctr_val; - return RISCV_EXCP_NONE; + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + return excp; } =20 - /* - * The kernel computes the perf delta by subtracting the current value= from - * the value it initialized previously (ctr_val). - */ - if (ctr_idx =3D=3D HPM_MCYCLE_IDX || ctr_idx =3D=3D HPM_MINSTRET_IDX) { - *val =3D riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, upper_= half) - - ctr_prev + ctr_val; - } else { - *val =3D ctr_val; - } + ctr_val =3D deposit64(ctr_val, 32, 32, val); =20 - return RISCV_EXCP_NONE; + return riscv_pmu_ctr_write(env, ctr_idx, ctr_val); } =20 static RISCVException read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val) { uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); - return riscv_pmu_read_ctr(env, val, false, ctr_idx); + uint64_t ctr_val; + RISCVException excp; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + *val =3D ctr_val; + + return excp; } =20 static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) { - uint32_t ctr_idx =3D riscv_pmu_csrno_to_ctr_idx(csrno); - return riscv_pmu_read_ctr(env, val, true, ctr_idx); + uint64_t ctr_val; + RISCVException excp; + + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + *val =3D ctr_val >> 32; + + return excp; } =20 static int rmw_cd_mhpmcounter(CPURISCVState *env, int ctr_idx, @@ -2935,63 +2870,39 @@ static RISCVException read_mcountinhibit(CPURISCVSt= ate *env, int csrno, static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, target_ulong val, uintptr_t ra) { - int cidx; - PMUCTRState *counter; + uint32_t cidx; RISCVCPU *cpu =3D env_archcpu(env); uint32_t present_ctrs =3D cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTER= EN_IR; target_ulong updated_ctrs =3D (env->mcountinhibit ^ val) & present_ctr= s; - uint64_t mhpmctr_val, prev_count, curr_count; - - /* WARL register - disable unavailable counters; TM bit is always 0 */ - env->mcountinhibit =3D val & present_ctrs; + uint64_t ctr_val; + bool inhibit_bit; + RISCVException excp; =20 /* Check if any other counter is also monitoring cycles/instructions */ for (cidx =3D 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { - if (!(updated_ctrs & BIT(cidx)) || - (cidx !=3D HPM_MCYCLE_IDX && cidx !=3D HPM_MINSTRET_IDX)) { + if (!get_field(updated_ctrs, BIT(cidx))) { continue; } =20 - counter =3D &env->pmu_ctrs[cidx]; + excp =3D riscv_pmu_ctr_read(env, cidx, &ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + qemu_log_mask(LOG_GUEST_ERROR, + "Reading the counter %d value is failed " + "while changing the inhibit bit", + cidx); + continue; + } =20 - if (!get_field(env->mcountinhibit, BIT(cidx))) { - counter->mhpmcounter_prev =3D - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - counter->mhpmcounterh_prev =3D - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); - } + inhibit_bit =3D get_field(val & present_ctrs, BIT(cidx)); + env->mcountinhibit =3D set_field(env->mcountinhibit, BIT(cidx), in= hibit_bit); =20 - if (cidx > 2) { - mhpmctr_val =3D counter->mhpmcounter_val; - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - mhpmctr_val =3D mhpmctr_val | - ((uint64_t)counter->mhpmcounterh_val << 32); - } - riscv_pmu_setup_timer(env, mhpmctr_val, cidx); - } - } else { - curr_count =3D riscv_pmu_ctr_get_fixed_counters_val(env, cidx,= false); - - mhpmctr_val =3D counter->mhpmcounter_val; - prev_count =3D counter->mhpmcounter_prev; - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - uint64_t tmp =3D - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); - - curr_count =3D curr_count | (tmp << 32); - mhpmctr_val =3D mhpmctr_val | - ((uint64_t)counter->mhpmcounterh_val << 32); - prev_count =3D prev_count | - ((uint64_t)counter->mhpmcounterh_prev << 32); - } - - /* Adjust the counter for later reads. */ - mhpmctr_val =3D curr_count - prev_count + mhpmctr_val; - counter->mhpmcounter_val =3D mhpmctr_val; - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - counter->mhpmcounterh_val =3D mhpmctr_val >> 32; - } + excp =3D riscv_pmu_ctr_write(env, cidx, ctr_val); + if (excp !=3D RISCV_EXCP_NONE) { + qemu_log_mask(LOG_GUEST_ERROR, + "Writing to the counter %d value is failed " + "while changing the inhibit bit", + cidx); + continue; } } =20 diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 18d790af0d..5083bbb1f2 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -339,10 +339,9 @@ static const VMStateDescription vmstate_pmu_ctr_state = =3D { .minimum_version_id =3D 2, .needed =3D pmu_needed, .fields =3D (const VMStateField[]) { - VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState), - VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState), - VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState), - VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState), + VMSTATE_UINT64(mhpmcounter_val, PMUCTRState), + VMSTATE_UINT64(mhpmcounter_prev, PMUCTRState), + VMSTATE_BOOL(overflowed, PMUCTRState), VMSTATE_END_OF_LIST() } }; diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index c503fffde1..5109fd14bf 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -80,120 +80,18 @@ void riscv_pmu_generate_fdt_node(void *fdt, uint32_t c= mask, char *pmu_name) } =20 static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx) -{ - if (ctr_idx < 3 || ctr_idx >=3D RV_MAX_MHPMCOUNTERS || - !(cpu->pmu_avail_ctrs & BIT(ctr_idx))) { - return false; - } else { - return true; - } -} - -static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx) { CPURISCVState *env =3D &cpu->env; =20 - if (riscv_pmu_counter_valid(cpu, ctr_idx) && - !get_field(env->mcountinhibit, BIT(ctr_idx))) { + if (!RISCV_PMU_CTR_IS_HPM(ctr_idx)) { return true; - } else { + } + + if (!(cpu->pmu_avail_ctrs & BIT(ctr_idx))) { return false; } -} =20 -/* - * Information needed to update counters: - * new_priv, new_virt: To correctly save starting snapshot for the newly - * started mode. Look at array being indexed with new= prv. - * old_priv, old_virt: To correctly select previous snapshot for old priv - * and compute delta. Also to select correct counter - * to inc. Look at arrays being indexed with env->pri= v. - * - * To avoid the complexity of calling this function, we assume that - * env->priv and env->virt_enabled contain old priv and old virt and - * new priv and new virt values are passed in as arguments. - */ -static void riscv_pmu_icount_update_priv(CPURISCVState *env, - target_ulong newpriv, bool new_vi= rt) -{ - uint64_t *snapshot_prev, *snapshot_new; - uint64_t current_icount; - uint64_t *counter_arr; - uint64_t delta; - - if (icount_enabled()) { - current_icount =3D icount_get_raw(); - } else { - current_icount =3D cpu_get_host_ticks(); - } - - if (env->virt_enabled) { - g_assert(env->priv <=3D PRV_S); - counter_arr =3D env->pmu_fixed_ctrs[1].counter_virt; - snapshot_prev =3D env->pmu_fixed_ctrs[1].counter_virt_prev; - } else { - counter_arr =3D env->pmu_fixed_ctrs[1].counter; - snapshot_prev =3D env->pmu_fixed_ctrs[1].counter_prev; - } - - if (new_virt) { - g_assert(newpriv <=3D PRV_S); - snapshot_new =3D env->pmu_fixed_ctrs[1].counter_virt_prev; - } else { - snapshot_new =3D env->pmu_fixed_ctrs[1].counter_prev; - } - - /* - * new_priv can be same as env->priv. So we need to calculate - * delta first before updating snapshot_new[new_priv]. - */ - delta =3D current_icount - snapshot_prev[env->priv]; - snapshot_new[newpriv] =3D current_icount; - - counter_arr[env->priv] +=3D delta; -} - -static void riscv_pmu_cycle_update_priv(CPURISCVState *env, - target_ulong newpriv, bool new_vir= t) -{ - uint64_t *snapshot_prev, *snapshot_new; - uint64_t current_ticks; - uint64_t *counter_arr; - uint64_t delta; - - if (icount_enabled()) { - current_ticks =3D icount_get(); - } else { - current_ticks =3D cpu_get_host_ticks(); - } - - if (env->virt_enabled) { - g_assert(env->priv <=3D PRV_S); - counter_arr =3D env->pmu_fixed_ctrs[0].counter_virt; - snapshot_prev =3D env->pmu_fixed_ctrs[0].counter_virt_prev; - } else { - counter_arr =3D env->pmu_fixed_ctrs[0].counter; - snapshot_prev =3D env->pmu_fixed_ctrs[0].counter_prev; - } - - if (new_virt) { - g_assert(newpriv <=3D PRV_S); - snapshot_new =3D env->pmu_fixed_ctrs[0].counter_virt_prev; - } else { - snapshot_new =3D env->pmu_fixed_ctrs[0].counter_prev; - } - - delta =3D current_ticks - snapshot_prev[env->priv]; - snapshot_new[newpriv] =3D current_ticks; - - counter_arr[env->priv] +=3D delta; -} - -void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv, - bool new_virt) -{ - riscv_pmu_cycle_update_priv(env, newpriv, new_virt); - riscv_pmu_icount_update_priv(env, newpriv, new_virt); + return env->pmu_vendor_support && env->pmu_vendor_support(env, ctr_idx= ); } =20 static int64_t pmu_icount_ticks_to_ns(int64_t value) @@ -249,51 +147,23 @@ static bool pmu_hpmevent_set_of_if_clear(CPURISCVStat= e *env, uint32_t ctr_idx) static void pmu_timer_trigger_irq(RISCVCPU *cpu, uint32_t ctr_idx) { CPURISCVState *env =3D &cpu->env; - PMUCTRState *counter; - int64_t irq_trigger_at; - uint64_t curr_ctr_val, curr_ctrh_val; + PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; uint64_t ctr_val; - - if (ctr_idx !=3D HPM_MINSTRET_IDX && - ctr_idx !=3D HPM_MCYCLE_IDX) { - return; - } - - if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { - return; - } + RISCVException excp; =20 /* Generate interrupt only if OF bit is clear */ if (pmu_hpmevent_is_of_set(env, ctr_idx)) { return; } =20 - counter =3D &env->pmu_ctrs[ctr_idx]; - if (counter->irq_overflow_left > 0) { - irq_trigger_at =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - counter->irq_overflow_left; - timer_mod_anticipate_ns(cpu->pmu_timer, irq_trigger_at); - counter->irq_overflow_left =3D 0; + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &ctr_val); + + if (excp !=3D RISCV_EXCP_NONE) { return; } =20 - riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctr_val, false, ctr_idx); - ctr_val =3D counter->mhpmcounter_val; - if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { - riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctrh_val, true, ctr_= idx); - curr_ctr_val =3D curr_ctr_val | (curr_ctrh_val << 32); - ctr_val =3D ctr_val | - ((uint64_t)counter->mhpmcounterh_val << 32); - } - - /* - * We can not accommodate for inhibited modes when setting up timer. C= heck - * if the counter has actually overflowed or not by comparing current - * counter value (accommodated for inhibited modes) with software writ= ten - * counter value. - */ - if (curr_ctr_val >=3D ctr_val) { - riscv_pmu_setup_timer(env, curr_ctr_val, ctr_idx); + if (!counter->overflowed) { + riscv_pmu_setup_timer(env, ctr_val, ctr_idx); return; } =20 @@ -302,6 +172,7 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, uint32= _t ctr_idx) riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1)); } } + counter->overflowed =3D false; } =20 /* Timer callback for instret and cycle counter overflow */ @@ -320,7 +191,7 @@ void riscv_pmu_timer_cb(void *priv) int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr= _idx) { uint64_t overflow_delta, overflow_at, curr_ns; - int64_t overflow_ns, overflow_left =3D 0; + uint64_t overflow_ns; RISCVCPU *cpu =3D env_archcpu(env); PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; =20 @@ -330,6 +201,11 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t= value, uint32_t ctr_idx) return -1; } =20 + if (counter->overflowed) { + pmu_timer_trigger_irq(cpu, ctr_idx); + return 0; + } + if (value) { overflow_delta =3D UINT64_MAX - value + 1; } else { @@ -338,28 +214,11 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_= t value, uint32_t ctr_idx) =20 /* * QEMU supports only int64_t timers while RISC-V counters are uint64_= t. - * Compute the leftover and save it so that it can be reprogrammed aga= in - * when timer expires. */ - if (overflow_delta > INT64_MAX) { - overflow_left =3D overflow_delta - INT64_MAX; - } - - if (ctr_idx =3D=3D HPM_MCYCLE_IDX || - ctr_idx =3D=3D HPM_MINSTRET_IDX) { - overflow_ns =3D pmu_icount_ticks_to_ns((int64_t)overflow_delta); - overflow_left =3D pmu_icount_ticks_to_ns(overflow_left) ; - } else { - return -1; - } + overflow_ns =3D pmu_icount_ticks_to_ns(overflow_delta); curr_ns =3D (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - overflow_at =3D curr_ns + overflow_ns; - if (overflow_at <=3D curr_ns) - overflow_at =3D UINT64_MAX; - - if (overflow_at > INT64_MAX) { - overflow_left +=3D overflow_at - INT64_MAX; - counter->irq_overflow_left =3D overflow_left; + if (uadd64_overflow(curr_ns, overflow_ns, &overflow_at) || + overflow_at > INT64_MAX) { overflow_at =3D INT64_MAX; } timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); @@ -426,3 +285,201 @@ uint32_t riscv_pmu_csrno_to_ctr_idx(int csrno) #undef HPMCOUNTER_START #undef CASE_RANGE } + +static uint64_t get_ticks(bool instructions) +{ + if (icount_enabled()) { + if (instructions) { + return icount_get_raw(); + } else { + return icount_get(); + } + } else { + return cpu_get_host_ticks(); + } +} + +static bool riscv_pmu_general_ctr_is_running(CPURISCVState *env, uint32_t = ctr_idx) +{ + #define PRIV_CASE(priv, nonvirt, nonvirth, virt, virth) { \ + case (priv): \ + if (env->virt_enabled) { \ + mask =3D (target_ulong) (virt); \ + maskh =3D (target_ulong) (virth); \ + } else { \ + mask =3D (target_ulong) (nonvirt); \ + maskh =3D (target_ulong) (nonvirth); \ + } \ + break; \ + } + + target_ulong event; + target_ulong eventh; + target_ulong mask =3D 0; + target_ulong maskh =3D 0; + + if (!riscv_pmu_counter_valid(env_archcpu(env), ctr_idx)) { + return false; + } + + if (get_field(env->mcountinhibit, BIT(ctr_idx))) { + return false; + } + + if (RISCV_PMU_CTR_IS_HPM(ctr_idx) && + (env->mhpmevent_val[ctr_idx] =3D=3D 0) && (env->mhpmeventh_val= [ctr_idx] =3D=3D 0)) { + return false; + } + + if ((riscv_cpu_cfg(env)->ext_smcntrpmf && !RISCV_PMU_CTR_IS_HPM(ctr_id= x)) || + (riscv_cpu_cfg(env)->ext_sscofpmf && RISCV_PMU_CTR_IS_HPM(ctr_idx)= )) { + if (ctr_idx =3D=3D HPM_MCYCLE_IDX) { + event =3D env->mcyclecfg; + eventh =3D env->mcyclecfgh; + } else if (ctr_idx =3D=3D HPM_MTIME_IDX) { + return true; + } else if (ctr_idx =3D=3D HPM_MINSTRET_IDX) { + event =3D env->minstretcfg; + eventh =3D env->minstretcfgh; + } else { + event =3D env->mhpmevent_val[ctr_idx]; + eventh =3D env->mhpmeventh_val[ctr_idx]; + } + + switch (env->priv) { + PRIV_CASE(PRV_U, MHPMEVENT_BIT_UINH, MHPMEVENTH_BIT_UINH, + MHPMEVENT_BIT_VUINH, MHPMEVENTH_BIT_VUINH); + PRIV_CASE(PRV_S, MHPMEVENT_BIT_SINH, MHPMEVENTH_BIT_SINH, + MHPMEVENT_BIT_VSINH, MHPMEVENTH_BIT_VSINH); + PRIV_CASE(PRV_M, MHPMEVENT_BIT_MINH, MHPMEVENTH_BIT_MINH, + MHPMEVENT_BIT_MINH, MHPMEVENTH_BIT_MINH); + } + + bool match =3D !(event & mask); + bool matchh =3D !(eventh & maskh); + return riscv_cpu_mxl(env) =3D=3D MXL_RV32 ? match && matchh : matc= h; + } else { + return true; + } + #undef PRIV_CASE +} + +static uint64_t riscv_pmu_ctr_delta_general(CPURISCVState *env, uint32_t c= tr_idx) +{ + PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; + if (riscv_pmu_general_ctr_is_running(env, ctr_idx)) { + return get_ticks(ctr_idx =3D=3D HPM_MINSTRET_IDX) - counter->mhpmc= ounter_prev; + } else { + /* + * We assume, what write() is called after each change of + * inhibited/filtered status. + * + * So if counter is inhibited or filtered now, the delta is zero. + * (By definition of `prev`). + * + * See documentation for PMUCTRState. + */ + return 0; + } +} + +RISCVException riscv_pmu_ctr_read_general(CPURISCVState *env, uint32_t ctr= _idx, + uint64_t *value) +{ + + PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; + int64_t delta =3D riscv_pmu_ctr_delta_general(env, ctr_idx); + uint64_t result; + + counter->overflowed |=3D + uadd64_overflow(counter->mhpmcounter_val, delta, &result); + *value =3D result; + return RISCV_EXCP_NONE; +} + +RISCVException riscv_pmu_ctr_read(CPURISCVState *env, uint32_t ctr_idx, + uint64_t *value) +{ + if (RISCV_PMU_CTR_IS_HPM(ctr_idx)) { + if (!env->pmu_ctr_read) { + *value =3D 0; + return RISCV_EXCP_NONE; + } + + return env->pmu_ctr_read(env, ctr_idx, value); + } else { + return riscv_pmu_ctr_read_general(env, ctr_idx, value); + } +} + +RISCVException riscv_pmu_ctr_write_general(CPURISCVState *env, uint32_t ct= r_idx, + uint64_t value) +{ + PMUCTRState *counter =3D &env->pmu_ctrs[ctr_idx]; + + counter->mhpmcounter_prev +=3D + riscv_pmu_ctr_delta_general(env, ctr_idx); + counter->mhpmcounter_val =3D value; + return RISCV_EXCP_NONE; +} + +RISCVException riscv_pmu_ctr_write(CPURISCVState *env, uint32_t ctr_idx, + uint64_t value) +{ + RISCVException excp; + + if (RISCV_PMU_CTR_IS_HPM(ctr_idx)) { + if (!env->pmu_ctr_write) { + value =3D 0; + return RISCV_EXCP_NONE; + } + + excp =3D env->pmu_ctr_write(env, ctr_idx, value); + } else { + excp =3D riscv_pmu_ctr_write_general(env, ctr_idx, value); + } + + if (excp !=3D RISCV_EXCP_NONE) { + return excp; + } + + riscv_pmu_setup_timer(env, value, ctr_idx); + + return RISCV_EXCP_NONE; +} + +void riscv_pmu_preserve_ctrs(CPURISCVState *env, riscv_pmu_preserved_ctrs_= t data) +{ + RISCVException excp; + + for (uint32_t ctr_idx =3D 0; ctr_idx < RV_MAX_MHPMCOUNTERS; ctr_idx++)= { + excp =3D riscv_pmu_ctr_read(env, ctr_idx, &data[ctr_idx]); + + if (excp !=3D RISCV_EXCP_NONE) { + qemu_log_mask(LOG_GUEST_ERROR, + "Reading the counter %d value is failed " + "while changing the privilige mode", + ctr_idx); + continue; + } + + } +} + +void riscv_pmu_restore_ctrs(CPURISCVState *env, riscv_pmu_preserved_ctrs_t= data) +{ + RISCVException excp; + + for (uint32_t ctr_idx =3D 0; ctr_idx < RV_MAX_MHPMCOUNTERS; ctr_idx++)= { + excp =3D riscv_pmu_ctr_write(env, ctr_idx, data[ctr_idx]); + + if (excp !=3D RISCV_EXCP_NONE) { + qemu_log_mask(LOG_GUEST_ERROR, + "Writing to the counter %d value is failed " + "while changing the privilige mode", + ctr_idx); + continue; + } + + } +} diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 97b167d8f2..283e311b04 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -22,15 +22,24 @@ #include "cpu.h" #include "qapi/error.h" =20 +#define RISCV_PMU_CTR_IS_HPM(x) ((x) > HPM_MINSTRET_IDX) + void riscv_pmu_timer_cb(void *priv); void riscv_pmu_init(RISCVCPU *cpu, Error **errp); void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name= ); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); -void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv, - bool new_virt); -RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, - bool upper_half, uint32_t ctr_idx); uint32_t riscv_pmu_csrno_to_ctr_idx(int csrno); +RISCVException riscv_pmu_ctr_read(CPURISCVState *env, uint32_t ctr_idx, + uint64_t *val); +RISCVException riscv_pmu_ctr_write(CPURISCVState *env, uint32_t ctr_idx, + uint64_t val); +RISCVException riscv_pmu_ctr_read_general(CPURISCVState *env, uint32_t ctr= _idx, + uint64_t *val); +RISCVException riscv_pmu_ctr_write_general(CPURISCVState *env, uint32_t ct= r_idx, + uint64_t val); +typedef uint64_t riscv_pmu_preserved_ctrs_t[RV_MAX_MHPMCOUNTERS]; +void riscv_pmu_preserve_ctrs(CPURISCVState *env, riscv_pmu_preserved_ctrs_= t data); +void riscv_pmu_restore_ctrs(CPURISCVState *env, riscv_pmu_preserved_ctrs_t= data); =20 #endif /* RISCV_PMU_H */ --=20 2.51.0 From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082800; cv=none; d=zohomail.com; s=zohoarc; b=Vrm5Y37wAbUOoy7zb89P+AlIg2/qTTtVvrdjlZW28NPMol+Qfq+qbopl8rY5W+R8UswxLK6Q0WNYHwx4OrYxe9PA0yXbf20OtOra74NGbBm7IZ2BGFHQn1HE5ZYE+0/f7bNg1WMenljdHO+QDOIM6vQXLCxeIMGfVWyH9XKpRK0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082800; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=GfraTUn3a2qoGbZSbxCtpfAGZXMUcHt2Eh4Hg4N27xI=; b=eTNlxVrwd8uZfYXwHfp4Kig5vM2xtzuGfEoAbg5L97zcK/H7earALgGSvhEdCSP1VARreUfgEypjsVLYEjAI+CbTWCPLrEZLW9GnN+Xw1wDlbe0J7bFk/zlHjHo9Dr+VRZgjCb8LK7kNqsKvIuUNVuMzDiz3WWavq8Dwy/53sWw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1766082799993531.4367278538264; Thu, 18 Dec 2025 10:33:19 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo3-0003wR-5s; Thu, 18 Dec 2025 13:32:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWIn3-0003nz-M3 for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:53 -0500 Received: from mail-lf1-x12e.google.com ([2a00:1450:4864:20::12e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWIn0-0007MM-Uh for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:53 -0500 Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-59584301f0cso1076086e87.0 for ; Thu, 18 Dec 2025 10:31:50 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082709; x=1766687509; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GfraTUn3a2qoGbZSbxCtpfAGZXMUcHt2Eh4Hg4N27xI=; b=P1Yi1bAAloEMMvYJkyl2MbvDSMUMH2699fskMcJuaeFbbyMsn0MMcgA3827l5cnhCU JkIe89mUAcf7TVYaFFT3zinp9QaanrbbPDTOmHYXhwhwIkEn1kKRxt/+8i5cFPqzayUS POTo62Pwc1NCci4eKNMkjJTW+RdyStLaDOHe4yOgnKdwNjWfHpv+y2n4UvgX0cX7zG9E Z75BwJG8mJ1czPAAEgEQYMPDoRaDzqV5GrDJSyGvsuVgiGVGFtT/IQ/Zrx34KNCM7stS /DTI3iI+3PaFcOabwtJbPpcSmCy9glVzELK7hI9oqXUOdd3UluIS2xqSVddcbRJ+0Y4T rlYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082709; x=1766687509; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=GfraTUn3a2qoGbZSbxCtpfAGZXMUcHt2Eh4Hg4N27xI=; b=DgmzhwGR/U2AdEOr9m9y3vgwiKdFKE49pMh1GgT3uO6YX8vapXf7iaZSk0k+ta3PhN y6aPVAnc5t7PliHyTBWJdjc5J2L9DPdQleiZ4EGOWC0C7YCSxaHjwiHSL2/+ZcvnZzwV TKiuhlW+cF/GQXlLzgW3d6eZ5NE4RXn/HHrwSK3Tir6Puyy8A1i6Uv0kSP3Mkn3ZZAXG dLld1ARdZEUccSjk/RgJlofdG/kdL6wHUl3uDeW3y1yN9FW5nmKlCkcITKxxAzmSm/E4 ZtZxfd7/Vnt3KMHSFyFOaUAvXC33wyVvmKJva9pcmtwpl9A0YfBHbUjyh2AiRnROWprZ /q3Q== X-Gm-Message-State: AOJu0Yy+zVhp3VoQMcvlJ5HP4p4+XsxaECpfuJwN2zH5U7//jmzpb8Yq 9JdqWKwKmQFv8Jj4Uo6hXFt3cyEuxL6Paz3trtBWP1OfAlv/uSC2Nn4NoMM3TaBz X-Gm-Gg: AY/fxX4xePouAym0IEwOhWYc2oycZAcm7wWwQjRf3PY3MmN/+Q27Cym/1kbOw5xDbSI tit+FC09i9KjvOkWPdSy2JduEUJWuTYnWK6bpYt9tFPxd3xtBfn6XtyMLsBYHBH0FKC8DimEWUr t60uhKwJ0GDz8vomkDhKlz/xxLSYju209/PsSMTuG3bNQeQhh2XiJtTQLTKnn8nHxD+XHhsR/lk XLDi+DqOpbBqWInQpOwDq4I4N624y5nXDDvhXo6ko+cVVMLZCtAhH4yIIgDMLhn3pGWSp1Wa097 xnz0Edk4kMOqCB6ZLgg93Vtbthp9zCfUxLvs5GG139xHIu0yoQAMF5XKId0opFNWyxN9HE3Cp6r 4KNy5HgkoxHRoEXGJD/hEfIvT7YPMjt19CyBHLK3eROTFP5MJphG08xQnE+8j8iOVsngpt4zd7L LYakh5vfKx4o7W X-Google-Smtp-Source: AGHT+IEOY3UAKtEKJJwOH9O/75J5rtspcTGIzPAy03x/oY4CQSVO8T4C+5mFQMX8bUN/zUo90H78dQ== X-Received: by 2002:a05:6512:10d5:b0:594:2dbb:723a with SMTP id 2adb3069b0e04-59a17d5da8bmr197282e87.39.1766082708424; Thu, 18 Dec 2025 10:31:48 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 5/6] target/riscv: Add PMU events implementation for `virt` Date: Thu, 18 Dec 2025 21:31:20 +0300 Message-ID: <20251218183122.408690-6-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::12e; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x12e.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:45 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082801488158500 Content-Type: text/plain; charset="utf-8" Add PMU events implementation for `virt` machine according to SBI spec. Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + hw/misc/virt_pmu.c | 142 +++++++++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 1 + hw/riscv/virt.c | 4 +- include/hw/misc/virt_pmu.h | 91 ++++++++++++++++++++++++ target/riscv/cpu.c | 8 +++ target/riscv/pmu.c | 53 -------------- target/riscv/pmu.h | 1 - 9 files changed, 248 insertions(+), 56 deletions(-) create mode 100644 hw/misc/virt_pmu.c create mode 100644 include/hw/misc/virt_pmu.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index fccd735c24..099200f711 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -150,6 +150,9 @@ config IOTKIT_SYSINFO config PVPANIC_COMMON bool =20 +config VIRT_PMU + bool + config PVPANIC_PCI bool default y if PCI_DEVICES diff --git a/hw/misc/meson.build b/hw/misc/meson.build index b1d8d8e5d2..977a3ac620 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -34,6 +34,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: file= s('sifive_e_prci.c')) system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'= )) system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'= )) system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.= c')) +specific_ss.add(when: 'CONFIG_VIRT_PMU', if_true: files('virt_pmu.c')) =20 subdir('macio') =20 diff --git a/hw/misc/virt_pmu.c b/hw/misc/virt_pmu.c new file mode 100644 index 0000000000..afba06de0e --- /dev/null +++ b/hw/misc/virt_pmu.c @@ -0,0 +1,142 @@ +/* + * RISC-V Virt machine PMU emulation. + * + * Copyright (c) 2025 Syntacore. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "target/riscv/cpu.h" +#include "target/riscv/pmu.h" +#include "include/hw/misc/virt_pmu.h" +#include "system/device_tree.h" + +#define SBI_CACHE_EVENT_ID_CNT (SBI_PMU_HW_CACHE_NODE - SBI_PMU_HW_CACHE_L= 1D + 1) +#define SBI_CACHE_OP_ID_CNT (SBI_PMU_HW_CACHE_OP_PREFETCH - SBI_PMU_HW_CAC= HE_OP_READ + 1) +#define SBI_EVT_CTR_SIZE (SBI_CACHE_EVENT_ID_CNT * SBI_CACHE_OP_ID_CNT + 3) + +void riscv_virt_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu= _name) +{ + uint32_t fdt_event_mhpmctr_map[SBI_EVT_CTR_SIZE][3] =3D {}; + uint32_t event_mhpmctr_idx =3D 0; + + uint32_t event_idx_low, event_idx_high; + + /* SBI_PMU_HW_CPU_CYCLES */ + fdt_event_mhpmctr_map[event_mhpmctr_idx][0] =3D cpu_to_be32(SBI_PMU_HW= _CPU_CYCLES); + fdt_event_mhpmctr_map[event_mhpmctr_idx][1] =3D cpu_to_be32(SBI_PMU_HW= _CPU_CYCLES); + fdt_event_mhpmctr_map[event_mhpmctr_idx][2] =3D cpu_to_be32(cmask | 1 = << 0); + event_mhpmctr_idx++; + + /* SBI_PMU_HW_INSTRUCTIONS */ + fdt_event_mhpmctr_map[event_mhpmctr_idx][0] =3D + cpu_to_be32(SBI_PMU_HW_INSTRUCTIONS); + + fdt_event_mhpmctr_map[event_mhpmctr_idx][1] =3D + cpu_to_be32(SBI_PMU_HW_INSTRUCTIONS); + + fdt_event_mhpmctr_map[event_mhpmctr_idx][2] =3D cpu_to_be32(cmask | 1 = << 2); + event_mhpmctr_idx++; + + /* Other generic type events */ + fdt_event_mhpmctr_map[event_mhpmctr_idx][0] =3D + cpu_to_be32(SBI_PMU_HW_CACHE_REFERENCES); + + fdt_event_mhpmctr_map[event_mhpmctr_idx][1] =3D + cpu_to_be32(SBI_PMU_HW_REF_CPU_CYCLES); + + fdt_event_mhpmctr_map[event_mhpmctr_idx][2] =3D cpu_to_be32(cmask); + event_mhpmctr_idx++; + + /* Cache type */ + for (uint32_t ev_id =3D 0; ev_id < SBI_CACHE_EVENT_ID_CNT; ++ev_id) { + for (uint32_t op_id =3D 0; op_id < SBI_CACHE_OP_ID_CNT; ++op_id) { + event_idx_low =3D FIELD_DP32(0, SBI_MHPMEVENT_CACHE, OP, op_id= ); + event_idx_low =3D FIELD_DP32(event_idx_low, SBI_MHPMEVENT_CACH= E, EVENT, ev_id); + event_idx_low =3D FIELD_DP32(event_idx_low, SBI_MHPMEVENT, TYP= E, + RISCV_SBI_EVENT_TYPE_CACHE); + event_idx_low =3D FIELD_DP32(event_idx_low, SBI_MHPMEVENT_CACH= E, RESULT, + SBI_PMU_HW_CACHE_RESULT_ACCESS); + + event_idx_high =3D FIELD_DP32(event_idx_low, SBI_MHPMEVENT_CAC= HE, RESULT, + SBI_PMU_HW_CACHE_RESULT_MISS); + + fdt_event_mhpmctr_map[event_mhpmctr_idx][0] =3D cpu_to_be32(ev= ent_idx_low); + fdt_event_mhpmctr_map[event_mhpmctr_idx][1] =3D cpu_to_be32(ev= ent_idx_high); + fdt_event_mhpmctr_map[event_mhpmctr_idx][2] =3D cpu_to_be32(cm= ask); + event_mhpmctr_idx++; + } + } + + g_assert(event_mhpmctr_idx <=3D SBI_EVT_CTR_SIZE); + + /* This a OpenSBI specific DT property documented in OpenSBI docs */ + qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters", + fdt_event_mhpmctr_map, + event_mhpmctr_idx * sizeof(fdt_event_mhpmctr_map[0])); +} + +bool riscv_virt_supported_events(CPURISCVState *env, uint32_t ctr_idx) +{ + uint32_t sbi_event_type =3D FIELD_EX32(env->mhpmevent_val[ctr_idx], + SBI_MHPMEVENT, TYPE); + uint32_t sbi_cache_event; + uint32_t sbi_cache_op; + uint32_t sbi_cache_result; + + switch (sbi_event_type) { + case RISCV_SBI_EVENT_TYPE_GEN: + return sbi_event_type <=3D SBI_PMU_HW_REF_CPU_CYCLES; + case RISCV_SBI_EVENT_TYPE_CACHE: + sbi_cache_event =3D FIELD_EX32(sbi_event_type, SBI_MHPMEVENT_CACHE= , EVENT); + sbi_cache_op =3D FIELD_EX32(sbi_event_type, SBI_MHPMEVENT_CACHE, O= P); + sbi_cache_result =3D FIELD_EX32(sbi_event_type, SBI_MHPMEVENT_CACH= E, RESULT); + + return sbi_cache_event <=3D SBI_PMU_HW_CACHE_NODE && + sbi_cache_op <=3D SBI_PMU_HW_CACHE_OP_PREFETCH && + sbi_cache_result <=3D SBI_PMU_HW_CACHE_RESULT_MISS; + default: + return false; + } +} + +RISCVException riscv_virt_pmu_ctr_read(CPURISCVState *env, uint32_t ctr_id= x, + uint64_t *value) +{ + uint32_t sbi_event_type =3D FIELD_EX32(env->mhpmevent_val[ctr_idx], + SBI_MHPMEVENT, TYPE); + + switch (sbi_event_type) { + /* If we want to handle some events separately */ + default: + /* In case we do not want handle it separately */ + return riscv_pmu_ctr_read_general(env, ctr_idx, value); + } +} + +RISCVException riscv_virt_pmu_ctr_write(CPURISCVState *env, uint32_t ctr_i= dx, + uint64_t value) +{ + uint32_t sbi_event_type =3D FIELD_EX32(env->mhpmevent_val[ctr_idx], + SBI_MHPMEVENT, TYPE); + + switch (sbi_event_type) { + /* If we want to handle some events separately */ + default: + /* In case we do not want handle it separately */ + return riscv_pmu_ctr_write_general(env, ctr_idx, value); + } +} diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index fc9c35bd98..920b65d733 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -49,6 +49,7 @@ config RISCV_VIRT imply VIRTIO_VGA imply TEST_DEVICES imply TPM_TIS_SYSBUS + select VIRT_PMU select DEVICE_TREE select RISCV_NUMA select GOLDFISH_RTC diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 17909206c7..7b0e6869db 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -30,7 +30,6 @@ #include "hw/char/serial-mm.h" #include "target/riscv/cpu.h" #include "hw/core/sysbus-fdt.h" -#include "target/riscv/pmu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/iommu.h" #include "hw/riscv/riscv-iommu-bits.h" @@ -58,6 +57,7 @@ #include "qapi/qapi-visit-common.h" #include "hw/virtio/virtio-iommu.h" #include "hw/uefi/var-service-api.h" +#include "hw/misc/virt_pmu.h" =20 /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU= . */ static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type) @@ -735,7 +735,7 @@ static void create_fdt_pmu(RISCVVirtState *s) =20 qemu_fdt_add_subnode(ms->fdt, pmu_name); qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); - riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name); + riscv_virt_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_nam= e); } =20 static void create_fdt_sockets(RISCVVirtState *s, diff --git a/include/hw/misc/virt_pmu.h b/include/hw/misc/virt_pmu.h new file mode 100644 index 0000000000..ea9ace5f6a --- /dev/null +++ b/include/hw/misc/virt_pmu.h @@ -0,0 +1,91 @@ +/* + * RISC-V Virt machine PMU header file. + * Copyright (C) 2025, Syntacore Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130= 1, USA. + * Also add information on how to contact you by electronic and paper mail. + */ + +#ifndef RISCV_VIRT_PMU_H +#define RISCV_VIRT_PMU_H + +#include "target/riscv/cpu.h" +#include "qapi/error.h" + +typedef enum riscv_sbi_pmu_types { + RISCV_SBI_EVENT_TYPE_GEN =3D 0x0, + RISCV_SBI_EVENT_TYPE_CACHE =3D 0x1, + RISCV_SBI_EVENT_TYPE_RAW =3D 0x2, + RISCV_SBI_EVENT_TYPE_RAW_V2 =3D 0x3, + RISCV_SBI_EVENT_TYPE_FIRMWARE =3D 0xf, +} riscv_sbi_pmu_types; + +REG32(SBI_MHPMEVENT, 0x323) + FIELD(SBI_MHPMEVENT, CODE, 0, 16) + FIELD(SBI_MHPMEVENT, TYPE, 16, 4) + +/* Generic type events */ + +typedef enum riscv_sbi_pmu_hw { + SBI_PMU_HW_NO_EVENT =3D 0x00000, + SBI_PMU_HW_CPU_CYCLES =3D 0x00001, + SBI_PMU_HW_INSTRUCTIONS =3D 0x00002, + SBI_PMU_HW_CACHE_REFERENCES =3D 0x00003, + SBI_PMU_HW_CACHE_MISSES =3D 0x00004, + SBI_PMU_HW_BRANCH_INSTRUCTIONS =3D 0x00005, + SBI_PMU_HW_BRANCH_MISSES =3D 0x00006, + SBI_PMU_HW_BUS_CYCLES =3D 0x00007, + SBI_PMU_HW_STALLED_CYCLES_FRONTEND =3D 0x00008, + SBI_PMU_HW_STALLED_CYCLES_BACKEND =3D 0x00009, + SBI_PMU_HW_REF_CPU_CYCLES =3D 0x0000A, +} riscv_sbi_pmu_hw; + +/* Cache type events */ + +typedef enum riscv_sbi_pmu_cache_event { + SBI_PMU_HW_CACHE_L1D =3D 0x0, + SBI_PMU_HW_CACHE_L1I =3D 0x1, + SBI_PMU_HW_CACHE_LL =3D 0x2, + SBI_PMU_HW_CACHE_DTLB =3D 0x3, + SBI_PMU_HW_CACHE_ITLB =3D 0x4, + SBI_PMU_HW_CACHE_BPU =3D 0x5, + SBI_PMU_HW_CACHE_NODE =3D 0x6, +} riscv_sbi_pmu_cache_event; + +typedef enum riscv_sbi_pmu_cache_op { + SBI_PMU_HW_CACHE_OP_READ =3D 0, + SBI_PMU_HW_CACHE_OP_WRITE =3D 1, + SBI_PMU_HW_CACHE_OP_PREFETCH =3D 2, +} riscv_sbi_pmu_cache_op; + +typedef enum riscv_sbi_pmu_cache_result { + SBI_PMU_HW_CACHE_RESULT_ACCESS =3D 0, + SBI_PMU_HW_CACHE_RESULT_MISS =3D 1, +} riscv_sbi_pmu_cache_result; + +REG32(SBI_MHPMEVENT_CACHE, 0x323) + FIELD(SBI_MHPMEVENT_CACHE, RESULT, 0, 1) + FIELD(SBI_MHPMEVENT_CACHE, OP, 1, 2) + FIELD(SBI_MHPMEVENT_CACHE, EVENT, 3, 13) + + +void riscv_virt_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu= _name); +bool riscv_virt_supported_events(CPURISCVState *env, uint32_t ctr_idx); +RISCVException riscv_virt_pmu_ctr_read(CPURISCVState *env, uint32_t ctr_id= x, + uint64_t *value); +RISCVException riscv_virt_pmu_ctr_write(CPURISCVState *env, uint32_t ctr_i= dx, + uint64_t value); + +#endif /* RISCV_VIRT_PMU_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 73d4280d7c..40853d7214 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -37,6 +37,7 @@ #include "kvm/kvm_riscv.h" #include "tcg/tcg-cpu.h" #include "tcg/tcg.h" +#include "hw/misc/virt_pmu.h" =20 /* RISC-V CPU definitions */ static const char riscv_single_letter_exts[] =3D "IEMAFDQCBPVH"; @@ -1125,6 +1126,13 @@ static void riscv_cpu_init(Object *obj) cpu->env.vext_ver =3D VEXT_VERSION_1_00_0; cpu->cfg.max_satp_mode =3D -1; =20 +#ifndef CONFIG_USER_ONLY + /* Default PMU implementation */ + env->pmu_ctr_write =3D riscv_virt_pmu_ctr_write; + env->pmu_ctr_read =3D riscv_virt_pmu_ctr_read; + env->pmu_vendor_support =3D riscv_virt_supported_events; +#endif /* CONFIG_USER_ONLY */ + if (mcc->def->profile) { mcc->def->profile->enabled =3D true; } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 5109fd14bf..899d5941bb 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -23,62 +23,9 @@ #include "cpu.h" #include "pmu.h" #include "exec/icount.h" -#include "system/device_tree.h" =20 #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */ =20 -/* - * To keep it simple, any event can be mapped to any programmable counters= in - * QEMU. The generic cycle & instruction count events can also be monitored - * using programmable counters. In that case, mcycle & minstret must conti= nue - * to provide the correct value as well. Heterogeneous PMU per hart is not - * supported yet. Thus, number of counters are same across all harts. - */ -void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name) -{ - uint32_t fdt_event_ctr_map[15] =3D {}; - - /* - * The event encoding is specified in the SBI specification - * Event idx is a 20bits wide number encoded as follows: - * event_idx[19:16] =3D type - * event_idx[15:0] =3D code - * The code field in cache events are encoded as follows: - * event_idx.code[15:3] =3D cache_id - * event_idx.code[2:1] =3D op_id - * event_idx.code[0:0] =3D result_id - */ - - /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */ - fdt_event_ctr_map[0] =3D cpu_to_be32(0x00000001); - fdt_event_ctr_map[1] =3D cpu_to_be32(0x00000001); - fdt_event_ctr_map[2] =3D cpu_to_be32(cmask | 1 << 0); - - /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */ - fdt_event_ctr_map[3] =3D cpu_to_be32(0x00000002); - fdt_event_ctr_map[4] =3D cpu_to_be32(0x00000002); - fdt_event_ctr_map[5] =3D cpu_to_be32(cmask | 1 << 2); - - /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[6] =3D cpu_to_be32(0x00010019); - fdt_event_ctr_map[7] =3D cpu_to_be32(0x00010019); - fdt_event_ctr_map[8] =3D cpu_to_be32(cmask); - - /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[9] =3D cpu_to_be32(0x0001001B); - fdt_event_ctr_map[10] =3D cpu_to_be32(0x0001001B); - fdt_event_ctr_map[11] =3D cpu_to_be32(cmask); - - /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[12] =3D cpu_to_be32(0x00010021); - fdt_event_ctr_map[13] =3D cpu_to_be32(0x00010021); - fdt_event_ctr_map[14] =3D cpu_to_be32(cmask); - - /* This a OpenSBI specific DT property documented in OpenSBI docs */ - qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters", - fdt_event_ctr_map, sizeof(fdt_event_ctr_map)); -} - static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx) { CPURISCVState *env =3D &cpu->env; diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 283e311b04..e0603b7e33 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -26,7 +26,6 @@ =20 void riscv_pmu_timer_cb(void *priv); void riscv_pmu_init(RISCVCPU *cpu, Error **errp); -void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name= ); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); uint32_t riscv_pmu_csrno_to_ctr_idx(int csrno); --=20 2.51.0 From nobody Sun Feb 8 21:48:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1766082811; cv=none; d=zohomail.com; s=zohoarc; b=NJnNNGnzWQzRli4MsKt2wEA12yVEDx8HdUToNUlaMr4DKjhsmtGfeewYGpB55Mk3RTM0ER9IjvkM8kfvS8FewDA3pmnXTwz3cXAg1oKpIvMw3+046T7rZrduc44sWblEeai5eaOCGjxdZnaEx/S7n28ZNvXr2xFEm/p/qbCJEmM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1766082811; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=kK/8BDYclAhYqhTuMn481i6aXarsHINljHJpjl1/oTo=; b=Q62Q2ewmQpIx8pH+Kya+/W5lrQ1pYrCMuL5O2p/XSDsLFc/AFsE3gH88hsoedo/z036bKlmbBiKz6fiSNwRCro1I7q16vHR8dgRncr8JP8eblPJ6WUKST4Cg/L44Z5V/1LbwV4wKv86ppEkLTmt58Ka/PR/kHF3KIdWNreuxyo4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1766082811043887.9852638694488; Thu, 18 Dec 2025 10:33:31 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vWIo8-0003xA-ID; Thu, 18 Dec 2025 13:33:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vWIn3-0003nx-Hi for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:53 -0500 Received: from mail-lf1-x133.google.com ([2a00:1450:4864:20::133]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vWIn1-0007MU-RQ for qemu-devel@nongnu.org; Thu, 18 Dec 2025 13:31:53 -0500 Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-598f8136a24so1060903e87.3 for ; Thu, 18 Dec 2025 10:31:51 -0800 (PST) Received: from NB-8855.Dlink ([81.201.19.27]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-59a185dd229sm46777e87.22.2025.12.18.10.31.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Dec 2025 10:31:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766082710; x=1766687510; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kK/8BDYclAhYqhTuMn481i6aXarsHINljHJpjl1/oTo=; b=cd+x5FMMdocZt4oUEE9OdiOPkVrGtPGcIfg3r/XG8/khanWut/f8RkkbU9tck94+rm 6+rDlkyvS9oPPbS0rnfi0dQjQPEx2FBGUgkUMZzTr/DhPbR369zZOBv6PjRtL3Ue3Jp3 FDgM4d8PQoOOzhnTm1x3ppfrcC8PVFTBD+DsIwGuRsUOvx/hoRTreQf/XpZcFxxJbRn4 yGWXoNtDN7j75LRnj2zs7VTzSwtF6Ip8Q4CmDBCI2YQlYQWV/3TQJlRp2oENuKWAdb12 vkbE2tQNr20wE7DNArF3WE0gS7IFRChQVxKyjfAQ0IVCmcLXAHLF2ecxISaUefgrxvb4 akfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766082710; x=1766687510; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kK/8BDYclAhYqhTuMn481i6aXarsHINljHJpjl1/oTo=; b=w6WDX3v0sCCRl5ujoE70E0cK+FjMbdOLSC5YOz0ZWkR+EQlgNeqsIn+gLNd7SesjGO eNTp3WyqynM0uKSjS4vfCXWJJIP7hjHeu6hBD8evqD6L92V5wFRAgzn5OCt7+D8pnQ2Q wfdaoFDsr2fjytANRX0Wmz9JOz7OYp6asBtW7JUvv8sW3xzfYXbJr/DLp0x7/vRbkkXL ZDtVxMVYK7/+lG0MwU2x3g4cwUPES/Uk81bdKeHEdpL6OjTc+vqLQG0GEm6mHWTEjmr7 o/NM5geAtMARWYmvnAiNTLES8rIuYk771bUyUKVulOQRh8PJ8l2JxGGKnx2dUkr8QA1H AV0Q== X-Gm-Message-State: AOJu0Yz6TZpa2Iw+MMMqoPVQXiJFmOhdCL/N5XICzRN1EBiq4iXcyWov kbFTiE/FUion+i3bRREDDd3IzRGOGMx6BfliaE9hyl1cLRT4yQ5+W6k+lrNRM5UJ X-Gm-Gg: AY/fxX4z9pg5Dth/v+aLomzboihxONZzIRvISBiFf64H0wQLn6f3P699fUYPPUrg0XC +sPfkH9cy+3j+lCGhix/0kfIjUi7NdIgoe+1K6UDfcOHBZR1Wc1r9uUx2x7NdYd/IJMe7l7aUSV G58IaeP4sZSJnlvsNqDfUKVsGXi+oKrmdDkt1DYbHZ5ZnWw0jyr8qB7L8qbWRWROMXdhDyxLI89 anw/05F/EojDvqdqx1KK6D+FGvx69k5u9MsIgmxqhQpKk0B8aerjogBIR7lcDWGJ+18nNgQrBS0 pbIv7GvJ0XK9edqPvKLmrAvhyuPzMJI7JsCtFhJZEuYgkBSVUi0tjotllqHSPeazUX9nPBPy/Ob sMAVISagVNEKPCICEw3YG2BEWpk9p+NOG5o+pfz4nOJlHjsRGY70u30hCw9TjW8povrIXKp/jX/ S/Fht6ir4v5o4H X-Google-Smtp-Source: AGHT+IHCrr1ZQ1hkiOQuV+5QCCfn9EDZMGOoyBKlU4Mr4qZVKArybDZZugepNcWsu+jcV6xbXAYhqA== X-Received: by 2002:a05:6512:b8b:b0:598:fd98:e9cd with SMTP id 2adb3069b0e04-59a17d4958fmr170938e87.1.1766082709350; Thu, 18 Dec 2025 10:31:49 -0800 (PST) From: Aleksandr Sergeev To: qemu-devel@nongnu.org Cc: halip0503@gmail.com, Aleksandr Sergeev Subject: [RFC PATCH 6/6] target/riscv/machine: Add smcntrpmf registers to VMStateDescription Date: Thu, 18 Dec 2025 21:31:21 +0300 Message-ID: <20251218183122.408690-7-sergeev0xef@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251218183122.408690-1-sergeev0xef@gmail.com> References: <20251218183122.408690-1-sergeev0xef@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::133; envelope-from=sergeev0xef@gmail.com; helo=mail-lf1-x133.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 18 Dec 2025 13:32:44 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1766082813363158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Aleksandr Sergeev Reviewed-by: Alexei Filippov --- target/riscv/machine.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 5083bbb1f2..2f6a5fc25c 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -474,6 +474,10 @@ const VMStateDescription vmstate_riscv_cpu =3D { VMSTATE_UINT32(env.mcounteren, RISCVCPU), VMSTATE_UINT32(env.scountinhibit, RISCVCPU), VMSTATE_UINT32(env.mcountinhibit, RISCVCPU), + VMSTATE_UINTTL(env.mcyclecfg, RISCVCPU), + VMSTATE_UINTTL(env.mcyclecfgh, RISCVCPU), + VMSTATE_UINTTL(env.minstretcfg, RISCVCPU), + VMSTATE_UINTTL(env.minstretcfgh, RISCVCPU), VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, = 0, vmstate_pmu_ctr_state, PMUCTRState), VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENT= S), --=20 2.51.0