* [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support
@ 2024-07-11 22:31 Atish Patra
2024-07-11 22:31 ` [PATCH v8 01/13] target/riscv: Combine set_mode and set_virt functions Atish Patra
` (13 more replies)
0 siblings, 14 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
This patch series adds the support for RISC-V ISA extension smcntrpmf (cycle and
privilege mode filtering) [1]. It is based on Kevin's earlier work but improves
it by actually implement privilege mode filtering by tracking the privilege
mode switches. This enables the privilege mode filtering for mhpmcounters as
well. However, Smcntrpmf/Sscofpmf must be enabled to leverage this.
The series is also available at [2] as well.
Changes in v8:
- Moved the config option to a separate patch at the end of the series.
- Fixed a comments recieved in v7 around setting INH bit based on available priv modes.
- Updated the RB/AB tags.
- Link to v7: https://lore.kernel.org/r/20240626-smcntrpmf_v7-v7-0-bb0f10af7fa9@rivosinc.com
Changes from v6->v7:
1. Fixed a compilation issue.
Changes from v5->v6:
1. Rebased on top of alister/riscv-to-apply.next (c50aabe132) and icount fix
patch[4] which may cause conflicts.
2. Fixed a bug in pmf logic related to VS<->HS transition and same mode
recording.
3. Merged assorted fixes PR as the changes are intertwined. [2]
4. Fix counter inhibit CSR behavior. This change now start counters from both
mhpmcounter and mcountinhibit writes. Previously cycle/inst timer was
only started on mhpmcounterx write.
5. Optimized the PMU timer setup code.
Changes from v4->v5:
1. Rebased on top of master(158a054c4d1a).
2. Fixed a bug for VS<->HS transition.
Changes from v3->v4:
1. Fixed the ordering of the ISA extension names in isa_edata_arr.
2. Added RB tags.
Changes from v2->v3:
1. Fixed the rebasing error in PATCH2.
2. Added RB tags.
3. Addressed other review comments.
Changes from v1->v2:
1. Implemented actual mode filtering for both icount and host ticks mode.
1. Addressed comments in v1.
2. Added Kevin's personal email address.
[1] https://github.com/riscv/riscv-smcntrpmf
[2] https://github.com/atishp04/qemu/tree/b4/smcntrpmf_v7
[3] https://lore.kernel.org/all/20240429-countinhibit_fix-v1-0-802ec1e99133@rivosinc.com/
[4] https://lore.kernel.org/qemu-riscv/20240618112649.76683-1-cleger@rivosinc.com/
Cc: Rajnesh Kanwal <rkanwal@rivosinc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
Atish Patra (7):
target/riscv: Fix the predicate functions for mhpmeventhX CSRs
target/riscv: Only set INH fields if priv mode is available
target/riscv: Implement privilege mode filtering for cycle/instret
target/riscv: Save counter values during countinhibit update
target/riscv: Enforce WARL behavior for scounteren/hcounteren
target/riscv: Do not setup pmu timer if OF is disabled
target/riscv: Expose the Smcntrpmf config
Kaiwen Xue (3):
target/riscv: Add cycle & instret privilege mode filtering properties
target/riscv: Add cycle & instret privilege mode filtering definitions
target/riscv: Add cycle & instret privilege mode filtering support
Rajnesh Kanwal (3):
target/riscv: Combine set_mode and set_virt functions.
target/riscv: Start counters from both mhpmcounter and mcountinhibit
target/riscv: More accurately model priv mode filtering.
target/riscv/cpu.c | 2 +
target/riscv/cpu.h | 20 ++-
target/riscv/cpu_bits.h | 41 +++++
target/riscv/cpu_cfg.h | 1 +
target/riscv/cpu_helper.c | 66 +++----
target/riscv/csr.c | 437 +++++++++++++++++++++++++++++++++++++---------
target/riscv/machine.c | 5 +-
target/riscv/op_helper.c | 17 +-
target/riscv/pmu.c | 181 +++++++++++++++++--
target/riscv/pmu.h | 4 +
10 files changed, 624 insertions(+), 150 deletions(-)
---
base-commit: 842a3d79a0e37cd3d685c4728308fac0d9bfd0bb
change-id: 20240626-smcntrpmf_v7-3b275d1da117
--
Regards,
Atish patra
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v8 01/13] target/riscv: Combine set_mode and set_virt functions.
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 02/13] target/riscv: Fix the predicate functions for mhpmeventhX CSRs Atish Patra
` (12 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Rajnesh Kanwal <rkanwal@rivosinc.com>
Combining riscv_cpu_set_virt_enabled() and riscv_cpu_set_mode()
functions. This is to make complete mode change information
available through a single function.
This allows to easily differentiate between HS->VS, VS->HS
and VS->VS transitions when executing state update codes.
For example: One use-case which inspired this change is
to update mode-specific instruction and cycle counters
which requires information of both prev mode and current
mode.
Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
target/riscv/cpu.h | 2 +-
target/riscv/cpu_helper.c | 57 +++++++++++++++++++++++------------------------
target/riscv/op_helper.c | 17 +++++---------
3 files changed, 35 insertions(+), 41 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 90b8f1b08f83..46faefd24e09 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -544,7 +544,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
#endif /* !CONFIG_USER_ONLY */
-void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en);
void riscv_translate_init(void);
G_NORETURN void riscv_raise_exception(CPURISCVState *env,
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3ab..10d3fdaed376 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -619,30 +619,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen)
env->geilen = geilen;
}
-/* This function can only be called to set virt when RVH is enabled */
-void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
-{
- /* Flush the TLB on all virt mode changes. */
- if (env->virt_enabled != enable) {
- tlb_flush(env_cpu(env));
- }
-
- env->virt_enabled = enable;
-
- if (enable) {
- /*
- * The guest external interrupts from an interrupt controller are
- * delivered only when the Guest/VM is running (i.e. V=1). This means
- * any guest external interrupt which is triggered while the Guest/VM
- * is not running (i.e. V=0) will be missed on QEMU resulting in guest
- * with sluggish response to serial console input and other I/O events.
- *
- * To solve this, we check and inject interrupt after setting V=1.
- */
- riscv_cpu_update_mip(env, 0, 0);
- }
-}
-
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
{
CPURISCVState *env = &cpu->env;
@@ -715,7 +691,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
}
}
-void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
{
g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
@@ -736,6 +712,28 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
* preemptive context switch. As a result, do both.
*/
env->load_res = -1;
+
+ if (riscv_has_ext(env, RVH)) {
+ /* Flush the TLB on all virt mode changes. */
+ if (env->virt_enabled != virt_en) {
+ tlb_flush(env_cpu(env));
+ }
+
+ env->virt_enabled = virt_en;
+ if (virt_en) {
+ /*
+ * The guest external interrupts from an interrupt controller are
+ * delivered only when the Guest/VM is running (i.e. V=1). This
+ * means any guest external interrupt which is triggered while the
+ * Guest/VM is not running (i.e. V=0) will be missed on QEMU
+ * resulting in guest with sluggish response to serial console
+ * input and other I/O events.
+ *
+ * To solve this, we check and inject interrupt after setting V=1.
+ */
+ riscv_cpu_update_mip(env, 0, 0);
+ }
+ }
}
/*
@@ -1648,6 +1646,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
+ bool virt = env->virt_enabled;
bool write_gva = false;
uint64_t s;
@@ -1778,7 +1777,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
htval = env->guest_phys_fault_addr;
- riscv_cpu_set_virt_enabled(env, 0);
+ virt = false;
} else {
/* Trap into HS mode */
env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
@@ -1799,7 +1798,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->htinst = tinst;
env->pc = (env->stvec >> 2 << 2) +
((async && (env->stvec & 3) == 1) ? cause * 4 : 0);
- riscv_cpu_set_mode(env, PRV_S);
+ riscv_cpu_set_mode(env, PRV_S, virt);
} else {
/* handle the trap in M-mode */
if (riscv_has_ext(env, RVH)) {
@@ -1815,7 +1814,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
mtval2 = env->guest_phys_fault_addr;
/* Trapping to M mode, virt is disabled */
- riscv_cpu_set_virt_enabled(env, 0);
+ virt = false;
}
s = env->mstatus;
@@ -1830,7 +1829,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
env->mtinst = tinst;
env->pc = (env->mtvec >> 2 << 2) +
((async && (env->mtvec & 3) == 1) ? cause * 4 : 0);
- riscv_cpu_set_mode(env, PRV_M);
+ riscv_cpu_set_mode(env, PRV_M, virt);
}
/*
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 2baf5bc3ca19..ec1408ba0fb1 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -264,7 +264,7 @@ void helper_cbo_inval(CPURISCVState *env, target_ulong address)
target_ulong helper_sret(CPURISCVState *env)
{
uint64_t mstatus;
- target_ulong prev_priv, prev_virt;
+ target_ulong prev_priv, prev_virt = env->virt_enabled;
if (!(env->priv >= PRV_S)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
@@ -307,11 +307,9 @@ target_ulong helper_sret(CPURISCVState *env)
if (prev_virt) {
riscv_cpu_swap_hypervisor_regs(env);
}
-
- riscv_cpu_set_virt_enabled(env, prev_virt);
}
- riscv_cpu_set_mode(env, prev_priv);
+ riscv_cpu_set_mode(env, prev_priv, prev_virt);
return retpc;
}
@@ -347,16 +345,13 @@ target_ulong helper_mret(CPURISCVState *env)
mstatus = set_field(mstatus, MSTATUS_MPRV, 0);
}
env->mstatus = mstatus;
- riscv_cpu_set_mode(env, prev_priv);
-
- if (riscv_has_ext(env, RVH)) {
- if (prev_virt) {
- riscv_cpu_swap_hypervisor_regs(env);
- }
- riscv_cpu_set_virt_enabled(env, prev_virt);
+ if (riscv_has_ext(env, RVH) && prev_virt) {
+ riscv_cpu_swap_hypervisor_regs(env);
}
+ riscv_cpu_set_mode(env, prev_priv, prev_virt);
+
return retpc;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 02/13] target/riscv: Fix the predicate functions for mhpmeventhX CSRs
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
2024-07-11 22:31 ` [PATCH v8 01/13] target/riscv: Combine set_mode and set_virt functions Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties Atish Patra
` (11 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
mhpmeventhX CSRs are available for RV32. The predicate function
should check that first before checking sscofpmf extension.
Fixes: 14664483457b ("target/riscv: Add sscofpmf extension support")
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/csr.c | 67 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 38 insertions(+), 29 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 432c59dc66be..3ad851707e5c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -227,6 +227,15 @@ static RISCVException sscofpmf(CPURISCVState *env, int csrno)
return RISCV_EXCP_NONE;
}
+static RISCVException sscofpmf_32(CPURISCVState *env, int csrno)
+{
+ if (riscv_cpu_mxl(env) != MXL_RV32) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return sscofpmf(env, csrno);
+}
+
static RISCVException any(CPURISCVState *env, int csrno)
{
return RISCV_EXCP_NONE;
@@ -5101,91 +5110,91 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent,
write_mhpmevent },
- [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
- [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf, read_mhpmeventh,
+ [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
2024-07-11 22:31 ` [PATCH v8 01/13] target/riscv: Combine set_mode and set_virt functions Atish Patra
2024-07-11 22:31 ` [PATCH v8 02/13] target/riscv: Fix the predicate functions for mhpmeventhX CSRs Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-15 0:42 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 04/13] target/riscv: Add cycle & instret privilege mode filtering definitions Atish Patra
` (10 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Kaiwen Xue <kaiwenx@rivosinc.com>
This adds the properties for ISA extension smcntrpmf. Patches
implementing it will follow.
Signed-off-by: Kaiwen Xue <kaiwenx@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/cpu.c | 1 +
target/riscv/cpu_cfg.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4760cb2cc17f..63f553c92b00 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
+ ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde523b..b1376beb1dab 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -74,6 +74,7 @@ struct RISCVCPUConfig {
bool ext_ztso;
bool ext_smstateen;
bool ext_sstc;
+ bool ext_smcntrpmf;
bool ext_svadu;
bool ext_svinval;
bool ext_svnapot;
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 04/13] target/riscv: Add cycle & instret privilege mode filtering definitions
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (2 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support Atish Patra
` (9 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Kaiwen Xue <kaiwenx@rivosinc.com>
This adds the definitions for ISA extension smcntrpmf.
Signed-off-by: Kaiwen Xue <kaiwenx@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/cpu.h | 6 ++++++
target/riscv/cpu_bits.h | 29 +++++++++++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 46faefd24e09..c5d289e5f4b9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -339,6 +339,12 @@ struct CPUArchState {
uint32_t mcountinhibit;
+ /* PMU cycle & instret privilege mode filtering */
+ target_ulong mcyclecfg;
+ target_ulong mcyclecfgh;
+ target_ulong minstretcfg;
+ target_ulong minstretcfgh;
+
/* PMU counter state */
PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index c257c5ed7dc9..5faa817453bb 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -397,6 +397,10 @@
/* Machine counter-inhibit register */
#define CSR_MCOUNTINHIBIT 0x320
+/* Machine counter configuration registers */
+#define CSR_MCYCLECFG 0x321
+#define CSR_MINSTRETCFG 0x322
+
#define CSR_MHPMEVENT3 0x323
#define CSR_MHPMEVENT4 0x324
#define CSR_MHPMEVENT5 0x325
@@ -427,6 +431,9 @@
#define CSR_MHPMEVENT30 0x33e
#define CSR_MHPMEVENT31 0x33f
+#define CSR_MCYCLECFGH 0x721
+#define CSR_MINSTRETCFGH 0x722
+
#define CSR_MHPMEVENT3H 0x723
#define CSR_MHPMEVENT4H 0x724
#define CSR_MHPMEVENT5H 0x725
@@ -884,6 +891,28 @@ typedef enum RISCVException {
/* PMU related bits */
#define MIE_LCOFIE (1 << IRQ_PMU_OVF)
+#define MCYCLECFG_BIT_MINH BIT_ULL(62)
+#define MCYCLECFGH_BIT_MINH BIT(30)
+#define MCYCLECFG_BIT_SINH BIT_ULL(61)
+#define MCYCLECFGH_BIT_SINH BIT(29)
+#define MCYCLECFG_BIT_UINH BIT_ULL(60)
+#define MCYCLECFGH_BIT_UINH BIT(28)
+#define MCYCLECFG_BIT_VSINH BIT_ULL(59)
+#define MCYCLECFGH_BIT_VSINH BIT(27)
+#define MCYCLECFG_BIT_VUINH BIT_ULL(58)
+#define MCYCLECFGH_BIT_VUINH BIT(26)
+
+#define MINSTRETCFG_BIT_MINH BIT_ULL(62)
+#define MINSTRETCFGH_BIT_MINH BIT(30)
+#define MINSTRETCFG_BIT_SINH BIT_ULL(61)
+#define MINSTRETCFGH_BIT_SINH BIT(29)
+#define MINSTRETCFG_BIT_UINH BIT_ULL(60)
+#define MINSTRETCFGH_BIT_UINH BIT(28)
+#define MINSTRETCFG_BIT_VSINH BIT_ULL(59)
+#define MINSTRETCFGH_BIT_VSINH BIT(27)
+#define MINSTRETCFG_BIT_VUINH BIT_ULL(58)
+#define MINSTRETCFGH_BIT_VUINH BIT(26)
+
#define MHPMEVENT_BIT_OF BIT_ULL(63)
#define MHPMEVENTH_BIT_OF BIT(31)
#define MHPMEVENT_BIT_MINH BIT_ULL(62)
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (3 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 04/13] target/riscv: Add cycle & instret privilege mode filtering definitions Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-15 0:46 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available Atish Patra
` (8 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Kaiwen Xue <kaiwenx@rivosinc.com>
QEMU only calculates dummy cycles and instructions, so there is no
actual means to stop the icount in QEMU. Hence this patch merely adds
the functionality of accessing the cfg registers, and cause no actual
effects on the counting of cycle and instret counters.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Kaiwen Xue <kaiwenx@rivosinc.com>
---
target/riscv/cpu_bits.h | 12 +++++
target/riscv/csr.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 149 insertions(+), 1 deletion(-)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 5faa817453bb..32b068f18aa5 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -926,6 +926,18 @@ typedef enum RISCVException {
#define MHPMEVENT_BIT_VUINH BIT_ULL(58)
#define MHPMEVENTH_BIT_VUINH BIT(26)
+#define MHPMEVENT_FILTER_MASK (MHPMEVENT_BIT_MINH | \
+ MHPMEVENT_BIT_SINH | \
+ MHPMEVENT_BIT_UINH | \
+ MHPMEVENT_BIT_VSINH | \
+ MHPMEVENT_BIT_VUINH)
+
+#define MHPMEVENTH_FILTER_MASK (MHPMEVENTH_BIT_MINH | \
+ MHPMEVENTH_BIT_SINH | \
+ MHPMEVENTH_BIT_UINH | \
+ MHPMEVENTH_BIT_VSINH | \
+ MHPMEVENTH_BIT_VUINH)
+
#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
#define MHPMEVENT_IDX_MASK 0xFFFFF
#define MHPMEVENT_SSCOF_RESVD 16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 3ad851707e5c..b814d176cbb8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -30,7 +30,6 @@
#include "qemu/guest-random.h"
#include "qapi/error.h"
-
/* CSR function table public API */
void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
{
@@ -236,6 +235,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, int csrno)
return sscofpmf(env, csrno);
}
+static RISCVException smcntrpmf(CPURISCVState *env, int csrno)
+{
+ if (!riscv_cpu_cfg(env)->ext_smcntrpmf) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno)
+{
+ if (riscv_cpu_mxl(env) != MXL_RV32) {
+ return RISCV_EXCP_ILLEGAL_INST;
+ }
+
+ return smcntrpmf(env, csrno);
+}
+
static RISCVException any(CPURISCVState *env, int csrno)
{
return RISCV_EXCP_NONE;
@@ -830,6 +847,111 @@ static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
#else /* CONFIG_USER_ONLY */
+static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->mcyclecfg;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno,
+ target_ulong val)
+{
+ uint64_t inh_avail_mask;
+
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ env->mcyclecfg = val;
+ } else {
+ /* Set xINH fields if priv mode supported */
+ inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MCYCLECFG_BIT_MINH;
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFG_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFG_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MCYCLECFG_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MCYCLECFG_BIT_VSINH : 0;
+ env->mcyclecfg = val & inh_avail_mask;
+ }
+
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->mcyclecfgh;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno,
+ target_ulong val)
+{
+ target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
+ MCYCLECFGH_BIT_MINH);
+
+ /* Set xINH fields if priv mode supported */
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFGH_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFGH_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MCYCLECFGH_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MCYCLECFGH_BIT_VSINH : 0;
+
+ env->mcyclecfgh = val & inh_avail_mask;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_minstretcfg(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->minstretcfg;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_minstretcfg(CPURISCVState *env, int csrno,
+ target_ulong val)
+{
+ uint64_t inh_avail_mask;
+
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ env->minstretcfg = val;
+ } else {
+ inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MINSTRETCFG_BIT_MINH;
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFG_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFG_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MINSTRETCFG_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MINSTRETCFG_BIT_VSINH : 0;
+ env->minstretcfg = val & inh_avail_mask;
+ }
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_minstretcfgh(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ *val = env->minstretcfgh;
+ return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_minstretcfgh(CPURISCVState *env, int csrno,
+ target_ulong val)
+{
+ target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
+ MINSTRETCFGH_BIT_MINH);
+
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFGH_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFGH_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MINSTRETCFGH_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MINSTRETCFGH_BIT_VSINH : 0;
+
+ env->minstretcfgh = val & inh_avail_mask;
+ return RISCV_EXCP_NONE;
+}
+
static RISCVException read_mhpmevent(CPURISCVState *env, int csrno,
target_ulong *val)
{
@@ -5051,6 +5173,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
write_mcountinhibit,
.min_priv_ver = PRIV_VERSION_1_11_0 },
+ [CSR_MCYCLECFG] = { "mcyclecfg", smcntrpmf, read_mcyclecfg,
+ write_mcyclecfg,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
+ [CSR_MINSTRETCFG] = { "minstretcfg", smcntrpmf, read_minstretcfg,
+ write_minstretcfg,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
+
[CSR_MHPMEVENT3] = { "mhpmevent3", any, read_mhpmevent,
write_mhpmevent },
[CSR_MHPMEVENT4] = { "mhpmevent4", any, read_mhpmevent,
@@ -5110,6 +5239,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
[CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent,
write_mhpmevent },
+ [CSR_MCYCLECFGH] = { "mcyclecfgh", smcntrpmf_32, read_mcyclecfgh,
+ write_mcyclecfgh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
+ [CSR_MINSTRETCFGH] = { "minstretcfgh", smcntrpmf_32, read_minstretcfgh,
+ write_minstretcfgh,
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
+
[CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf_32, read_mhpmeventh,
write_mhpmeventh,
.min_priv_ver = PRIV_VERSION_1_12_0 },
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (4 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-15 0:49 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 07/13] target/riscv: Implement privilege mode filtering for cycle/instret Atish Patra
` (7 subsequent siblings)
13 siblings, 1 reply; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
Currently, the INH fields are set in mhpmevent uncoditionally
without checking if a particular priv mode is supported or not.
Suggested-by: Alistair Francis <alistair23@gmail.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/csr.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b814d176cbb8..121996edab4b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -967,13 +967,24 @@ static RISCVException write_mhpmevent(CPURISCVState *env, int csrno,
{
int evt_index = csrno - CSR_MCOUNTINHIBIT;
uint64_t mhpmevt_val = val;
-
- env->mhpmevent_val[evt_index] = val;
+ uint64_t inh_avail_mask;
if (riscv_cpu_mxl(env) == MXL_RV32) {
+ env->mhpmevent_val[evt_index] = val;
mhpmevt_val = mhpmevt_val |
((uint64_t)env->mhpmeventh_val[evt_index] << 32);
+ } else {
+ inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH;
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENT_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH : 0;
+ mhpmevt_val = val & inh_avail_mask;
+ env->mhpmevent_val[evt_index] = mhpmevt_val;
}
+
riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
return RISCV_EXCP_NONE;
@@ -993,11 +1004,21 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno,
target_ulong val)
{
int evt_index = csrno - CSR_MHPMEVENT3H + 3;
- uint64_t mhpmevth_val = val;
+ uint64_t mhpmevth_val;
uint64_t mhpmevt_val = env->mhpmevent_val[evt_index];
+ target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
+ MHPMEVENTH_BIT_MINH);
+
+ inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0;
+ inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0;
+ inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+ riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0;
+ mhpmevth_val = val & inh_avail_mask;
mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32);
- env->mhpmeventh_val[evt_index] = val;
+ env->mhpmeventh_val[evt_index] = mhpmevth_val;
riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 07/13] target/riscv: Implement privilege mode filtering for cycle/instret
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (5 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 08/13] target/riscv: Save counter values during countinhibit update Atish Patra
` (6 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
Privilege mode filtering can also be emulated for cycle/instret by
tracking host_ticks/icount during each privilege mode switch. This
patch implements that for both cycle/instret and mhpmcounters. The
first one requires Smcntrpmf while the other one requires Sscofpmf
to be enabled.
The cycle/instret are still computed using host ticks when icount
is not enabled. Otherwise, they are computed using raw icount which
is more accurate in icount mode.
Co-Developed-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/cpu.h | 11 +++++
target/riscv/cpu_helper.c | 9 +++-
target/riscv/csr.c | 117 ++++++++++++++++++++++++++++++++--------------
target/riscv/pmu.c | 92 ++++++++++++++++++++++++++++++++++++
target/riscv/pmu.h | 2 +
5 files changed, 194 insertions(+), 37 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c5d289e5f4b9..d56d640b06be 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -158,6 +158,15 @@ typedef struct PMUCTRState {
target_ulong irq_overflow_left;
} PMUCTRState;
+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 = 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 */
@@ -354,6 +363,8 @@ struct CPUArchState {
/* PMU event selector configured values for RV32 */
target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];
+ PMUFixedCtrState pmu_fixed_ctrs[2];
+
target_ulong sscratch;
target_ulong mscratch;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 10d3fdaed376..395a1d914061 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -695,9 +695,14 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
{
g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
- if (icount_enabled() && newpriv != env->priv) {
- riscv_itrigger_update_priv(env);
+ if (newpriv != env->priv || env->virt_enabled != virt_en) {
+ if (icount_enabled()) {
+ riscv_itrigger_update_priv(env);
+ }
+
+ riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en);
}
+
/* tlb_flush is unnecessary as mode is contained in mmu_idx */
env->priv = newpriv;
env->xl = cpu_recompute_xl(env);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 121996edab4b..53f1a7ff00db 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -787,36 +787,16 @@ static RISCVException write_vcsr(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+#if defined(CONFIG_USER_ONLY)
/* User Timers and Counters */
-static target_ulong get_ticks(bool shift, bool instructions)
+static target_ulong get_ticks(bool shift)
{
- int64_t val;
- target_ulong result;
-
-#if !defined(CONFIG_USER_ONLY)
- if (icount_enabled()) {
- if (instructions) {
- val = icount_get_raw();
- } else {
- val = icount_get();
- }
- } else {
- val = cpu_get_host_ticks();
- }
-#else
- val = cpu_get_host_ticks();
-#endif
-
- if (shift) {
- result = val >> 32;
- } else {
- result = val;
- }
+ int64_t val = cpu_get_host_ticks();
+ target_ulong result = shift ? val >> 32 : val;
return result;
}
-#if defined(CONFIG_USER_ONLY)
static RISCVException read_time(CPURISCVState *env, int csrno,
target_ulong *val)
{
@@ -834,14 +814,14 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
static RISCVException read_hpmcounter(CPURISCVState *env, int csrno,
target_ulong *val)
{
- *val = get_ticks(false, (csrno == CSR_INSTRET));
+ *val = get_ticks(false);
return RISCV_EXCP_NONE;
}
static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
target_ulong *val)
{
- *val = get_ticks(true, (csrno == CSR_INSTRETH));
+ *val = get_ticks(true);
return RISCV_EXCP_NONE;
}
@@ -1025,17 +1005,82 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env,
+ int counter_idx,
+ bool upper_half)
+{
+ int inst = riscv_pmu_ctr_monitor_instructions(env, counter_idx);
+ uint64_t *counter_arr_virt = env->pmu_fixed_ctrs[inst].counter_virt;
+ uint64_t *counter_arr = env->pmu_fixed_ctrs[inst].counter;
+ target_ulong result = 0;
+ uint64_t curr_val = 0;
+ uint64_t cfg_val = 0;
+
+ if (counter_idx == 0) {
+ cfg_val = upper_half ? ((uint64_t)env->mcyclecfgh << 32) :
+ env->mcyclecfg;
+ } else if (counter_idx == 2) {
+ cfg_val = upper_half ? ((uint64_t)env->minstretcfgh << 32) :
+ env->minstretcfg;
+ } else {
+ cfg_val = upper_half ?
+ ((uint64_t)env->mhpmeventh_val[counter_idx] << 32) :
+ env->mhpmevent_val[counter_idx];
+ cfg_val &= MHPMEVENT_FILTER_MASK;
+ }
+
+ if (!cfg_val) {
+ if (icount_enabled()) {
+ curr_val = inst ? icount_get_raw() : icount_get();
+ } else {
+ curr_val = cpu_get_host_ticks();
+ }
+
+ goto done;
+ }
+
+ if (!(cfg_val & MCYCLECFG_BIT_MINH)) {
+ curr_val += counter_arr[PRV_M];
+ }
+
+ if (!(cfg_val & MCYCLECFG_BIT_SINH)) {
+ curr_val += counter_arr[PRV_S];
+ }
+
+ if (!(cfg_val & MCYCLECFG_BIT_UINH)) {
+ curr_val += counter_arr[PRV_U];
+ }
+
+ if (!(cfg_val & MCYCLECFG_BIT_VSINH)) {
+ curr_val += counter_arr_virt[PRV_S];
+ }
+
+ if (!(cfg_val & MCYCLECFG_BIT_VUINH)) {
+ curr_val += counter_arr_virt[PRV_U];
+ }
+
+done:
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ result = upper_half ? curr_val >> 32 : curr_val;
+ } else {
+ result = curr_val;
+ }
+
+ return result;
+}
+
static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno,
target_ulong val)
{
int ctr_idx = csrno - CSR_MCYCLE;
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
uint64_t mhpmctr_val = val;
- bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx);
counter->mhpmcounter_val = val;
- if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || instr) {
- counter->mhpmcounter_prev = get_ticks(false, instr);
+ if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+ counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
+ ctr_idx, false);
if (ctr_idx > 2) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
mhpmctr_val = mhpmctr_val |
@@ -1058,12 +1103,13 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno,
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
uint64_t mhpmctr_val = counter->mhpmcounter_val;
uint64_t mhpmctrh_val = val;
- bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx);
counter->mhpmcounterh_val = val;
mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32);
- if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || instr) {
- counter->mhpmcounterh_prev = get_ticks(true, instr);
+ if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+ counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
+ ctr_idx, true);
if (ctr_idx > 2) {
riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx);
}
@@ -1082,7 +1128,6 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
counter->mhpmcounter_prev;
target_ulong ctr_val = upper_half ? counter->mhpmcounterh_val :
counter->mhpmcounter_val;
- bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx);
if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
/*
@@ -1103,8 +1148,10 @@ static 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) || instr) {
- *val = get_ticks(upper_half, instr) - ctr_prev + ctr_val;
+ if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+ *val = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, upper_half) -
+ ctr_prev + ctr_val;
} else {
*val = ctr_val;
}
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index 0e7d58b8a5c2..ac648cff8d7c 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
+#include "qemu/timer.h"
#include "cpu.h"
#include "pmu.h"
#include "sysemu/cpu-timers.h"
@@ -176,6 +177,97 @@ static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx)
return 0;
}
+/*
+ * 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 newprv.
+ * 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->priv.
+ *
+ * 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_virt)
+{
+ uint64_t *snapshot_prev, *snapshot_new;
+ uint64_t current_icount;
+ uint64_t *counter_arr;
+ uint64_t delta;
+
+ if (icount_enabled()) {
+ current_icount = icount_get_raw();
+ } else {
+ current_icount = cpu_get_host_ticks();
+ }
+
+ if (env->virt_enabled) {
+ counter_arr = env->pmu_fixed_ctrs[1].counter_virt;
+ snapshot_prev = env->pmu_fixed_ctrs[1].counter_virt_prev;
+ } else {
+ counter_arr = env->pmu_fixed_ctrs[1].counter;
+ snapshot_prev = env->pmu_fixed_ctrs[1].counter_prev;
+ }
+
+ if (new_virt) {
+ snapshot_new = env->pmu_fixed_ctrs[1].counter_virt_prev;
+ } else {
+ snapshot_new = 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 = current_icount - snapshot_prev[env->priv];
+ snapshot_new[newpriv] = current_icount;
+
+ counter_arr[env->priv] += delta;
+}
+
+static void riscv_pmu_cycle_update_priv(CPURISCVState *env,
+ target_ulong newpriv, bool new_virt)
+{
+ uint64_t *snapshot_prev, *snapshot_new;
+ uint64_t current_ticks;
+ uint64_t *counter_arr;
+ uint64_t delta;
+
+ if (icount_enabled()) {
+ current_ticks = icount_get();
+ } else {
+ current_ticks = cpu_get_host_ticks();
+ }
+
+ if (env->virt_enabled) {
+ counter_arr = env->pmu_fixed_ctrs[0].counter_virt;
+ snapshot_prev = env->pmu_fixed_ctrs[0].counter_virt_prev;
+ } else {
+ counter_arr = env->pmu_fixed_ctrs[0].counter;
+ snapshot_prev = env->pmu_fixed_ctrs[0].counter_prev;
+ }
+
+ if (new_virt) {
+ snapshot_new = env->pmu_fixed_ctrs[0].counter_virt_prev;
+ } else {
+ snapshot_new = env->pmu_fixed_ctrs[0].counter_prev;
+ }
+
+ delta = current_ticks - snapshot_prev[env->priv];
+ snapshot_new[newpriv] = current_ticks;
+
+ counter_arr[env->priv] += 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);
+}
+
int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx)
{
uint32_t ctr_idx;
diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index 7c0ad661e050..ca40cfeed647 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -34,5 +34,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx);
void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
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);
#endif /* RISCV_PMU_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 08/13] target/riscv: Save counter values during countinhibit update
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (6 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 07/13] target/riscv: Implement privilege mode filtering for cycle/instret Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 09/13] target/riscv: Enforce WARL behavior for scounteren/hcounteren Atish Patra
` (5 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
Currently, if a counter monitoring cycle/instret is stopped via
mcountinhibit we just update the state while the value is saved
during the next read. This is not accurate as the read may happen
many cycles after the counter is stopped. Ideally, the read should
return the value saved when the counter is stopped.
Thus, save the value of the counter during the inhibit update
operation and return that value during the read if corresponding bit
in mcountihibit is set.
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/cpu.h | 1 -
target/riscv/csr.c | 34 ++++++++++++++++++++++------------
target/riscv/machine.c | 5 ++---
3 files changed, 24 insertions(+), 16 deletions(-)
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index d56d640b06be..91fe2a46ba35 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -153,7 +153,6 @@ typedef struct PMUCTRState {
target_ulong mhpmcounter_prev;
/* Snapshort value of a counter in RV32 */
target_ulong mhpmcounterh_prev;
- bool started;
/* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
target_ulong irq_overflow_left;
} PMUCTRState;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 53f1a7ff00db..5e76ad5a350c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1131,17 +1131,11 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
/*
- * Counter should not increment if inhibit bit is set. We can't really
- * stop the icount counting. Just return the counter value written by
- * the supervisor to indicate that counter was not incremented.
+ * Counter should not increment if inhibit bit is set. Just return the
+ * current counter value.
*/
- if (!counter->started) {
- *val = ctr_val;
- return RISCV_EXCP_NONE;
- } else {
- /* Mark that the counter has been stopped */
- counter->started = false;
- }
+ *val = ctr_val;
+ return RISCV_EXCP_NONE;
}
/*
@@ -2183,9 +2177,25 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
/* Check if any other counter is also monitoring cycles/instructions */
for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
- if (!get_field(env->mcountinhibit, BIT(cidx))) {
counter = &env->pmu_ctrs[cidx];
- counter->started = true;
+ if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
+ /*
+ * Update the counter value for cycle/instret as we can't stop the
+ * host ticks. But we should show the current value at this moment.
+ */
+ if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
+ riscv_pmu_ctr_monitor_instructions(env, cidx)) {
+ counter->mhpmcounter_val =
+ riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) -
+ counter->mhpmcounter_prev +
+ counter->mhpmcounter_val;
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ counter->mhpmcounterh_val =
+ riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) -
+ counter->mhpmcounterh_prev +
+ counter->mhpmcounterh_val;
+ }
+ }
}
}
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 76f2150f78b5..492c2c6d9d79 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -320,15 +320,14 @@ static bool pmu_needed(void *opaque)
static const VMStateDescription vmstate_pmu_ctr_state = {
.name = "cpu/pmu",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.needed = pmu_needed,
.fields = (const VMStateField[]) {
VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState),
VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
- VMSTATE_BOOL(started, PMUCTRState),
VMSTATE_END_OF_LIST()
}
};
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 09/13] target/riscv: Enforce WARL behavior for scounteren/hcounteren
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (7 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 08/13] target/riscv: Save counter values during countinhibit update Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 10/13] target/riscv: Start counters from both mhpmcounter and mcountinhibit Atish Patra
` (4 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
scounteren/hcountern are also WARL registers similar to mcountern.
Only set the bits for the available counters during the write to
preserve the WARL behavior.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
---
target/riscv/csr.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5e76ad5a350c..5ef641918120 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3063,7 +3063,11 @@ static RISCVException read_scounteren(CPURISCVState *env, int csrno,
static RISCVException write_scounteren(CPURISCVState *env, int csrno,
target_ulong val)
{
- env->scounteren = val;
+ RISCVCPU *cpu = env_archcpu(env);
+
+ /* WARL register - disable unavailable counters */
+ env->scounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM |
+ COUNTEREN_IR);
return RISCV_EXCP_NONE;
}
@@ -3722,7 +3726,11 @@ static RISCVException read_hcounteren(CPURISCVState *env, int csrno,
static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
target_ulong val)
{
- env->hcounteren = val;
+ RISCVCPU *cpu = env_archcpu(env);
+
+ /* WARL register - disable unavailable counters */
+ env->hcounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM |
+ COUNTEREN_IR);
return RISCV_EXCP_NONE;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 10/13] target/riscv: Start counters from both mhpmcounter and mcountinhibit
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (8 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 09/13] target/riscv: Enforce WARL behavior for scounteren/hcounteren Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 11/13] target/riscv: More accurately model priv mode filtering Atish Patra
` (3 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Rajnesh Kanwal <rkanwal@rivosinc.com>
Currently we start timer counter from write_mhpmcounter path only
without checking for mcountinhibit bit. This changes adds mcountinhibit
check and also programs the counter from write_mcountinhibit as well.
When a counter is stopped using mcountinhibit we simply update
the value of the counter based on current host ticks and save
it for future reads.
We don't need to disable running timer as pmu_timer_trigger_irq
will discard the interrupt if the counter has been inhibited.
Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
target/riscv/csr.c | 75 ++++++++++++++++++++++++++++++++++++++----------------
target/riscv/pmu.c | 3 +--
2 files changed, 54 insertions(+), 24 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5ef641918120..ff06276192dd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1077,8 +1077,9 @@ static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno,
uint64_t mhpmctr_val = val;
counter->mhpmcounter_val = val;
- if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
- riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+ if (!get_field(env->mcountinhibit, BIT(ctr_idx)) &&
+ (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) {
counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
ctr_idx, false);
if (ctr_idx > 2) {
@@ -1106,8 +1107,9 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno,
counter->mhpmcounterh_val = val;
mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32);
- if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
- riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+ if (!get_field(env->mcountinhibit, BIT(ctr_idx)) &&
+ (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) {
counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
ctr_idx, true);
if (ctr_idx > 2) {
@@ -2170,31 +2172,60 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
int cidx;
PMUCTRState *counter;
RISCVCPU *cpu = env_archcpu(env);
+ uint32_t present_ctrs = cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR;
+ target_ulong updated_ctrs = (env->mcountinhibit ^ val) & present_ctrs;
+ uint64_t mhpmctr_val, prev_count, curr_count;
/* WARL register - disable unavailable counters; TM bit is always 0 */
- env->mcountinhibit =
- val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR);
+ env->mcountinhibit = val & present_ctrs;
/* Check if any other counter is also monitoring cycles/instructions */
for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
- counter = &env->pmu_ctrs[cidx];
- if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
- /*
- * Update the counter value for cycle/instret as we can't stop the
- * host ticks. But we should show the current value at this moment.
- */
- if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
- riscv_pmu_ctr_monitor_instructions(env, cidx)) {
- counter->mhpmcounter_val =
- riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) -
- counter->mhpmcounter_prev +
- counter->mhpmcounter_val;
+ if (!(updated_ctrs & BIT(cidx)) ||
+ (!riscv_pmu_ctr_monitor_cycles(env, cidx) &&
+ !riscv_pmu_ctr_monitor_instructions(env, cidx))) {
+ continue;
+ }
+
+ counter = &env->pmu_ctrs[cidx];
+
+ if (!get_field(env->mcountinhibit, BIT(cidx))) {
+ counter->mhpmcounter_prev =
+ riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false);
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ counter->mhpmcounterh_prev =
+ riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true);
+ }
+
+ if (cidx > 2) {
+ mhpmctr_val = counter->mhpmcounter_val;
if (riscv_cpu_mxl(env) == MXL_RV32) {
- counter->mhpmcounterh_val =
- riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) -
- counter->mhpmcounterh_prev +
- counter->mhpmcounterh_val;
+ mhpmctr_val = mhpmctr_val |
+ ((uint64_t)counter->mhpmcounterh_val << 32);
}
+ riscv_pmu_setup_timer(env, mhpmctr_val, cidx);
+ }
+ } else {
+ curr_count = riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false);
+
+ mhpmctr_val = counter->mhpmcounter_val;
+ prev_count = counter->mhpmcounter_prev;
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ uint64_t tmp =
+ riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true);
+
+ curr_count = curr_count | (tmp << 32);
+ mhpmctr_val = mhpmctr_val |
+ ((uint64_t)counter->mhpmcounterh_val << 32);
+ prev_count = prev_count |
+ ((uint64_t)counter->mhpmcounterh_prev << 32);
+ }
+
+ /* Adjust the counter for later reads. */
+ mhpmctr_val = curr_count - prev_count + mhpmctr_val;
+ counter->mhpmcounter_val = mhpmctr_val;
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ counter->mhpmcounterh_val = mhpmctr_val >> 32;
}
}
}
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index ac648cff8d7c..63420d9f3679 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -285,8 +285,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx)
}
ctr_idx = GPOINTER_TO_UINT(value);
- if (!riscv_pmu_counter_enabled(cpu, ctr_idx) ||
- get_field(env->mcountinhibit, BIT(ctr_idx))) {
+ if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) {
return -1;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 11/13] target/riscv: More accurately model priv mode filtering.
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (9 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 10/13] target/riscv: Start counters from both mhpmcounter and mcountinhibit Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 12/13] target/riscv: Do not setup pmu timer if OF is disabled Atish Patra
` (2 subsequent siblings)
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
From: Rajnesh Kanwal <rkanwal@rivosinc.com>
In case of programmable counters configured to count inst/cycles
we often end-up with counter not incrementing at all from kernel's
perspective.
For example:
- Kernel configures hpm3 to count instructions and sets hpmcounter
to -10000 and all modes except U mode are inhibited.
- In QEMU we configure a timer to expire after ~10000 instructions.
- Problem is, it's often the case that kernel might not even schedule
Umode task and we hit the timer callback in QEMU.
- In the timer callback we inject the interrupt into kernel, kernel
runs the handler and reads hpmcounter3 value.
- Given QEMU maintains individual counters to count for each privilege
mode, and given umode never ran, the umode counter didn't increment
and QEMU returns same value as was programmed by the kernel when
starting the counter.
- Kernel checks for overflow using previous and current value of the
counter and reprograms the counter given there wasn't an overflow
as per the counter value. (Which itself is a problem. We have QEMU
telling kernel that counter3 overflowed but the counter value
returned by QEMU doesn't seem to reflect that.).
This change makes sure that timer is reprogrammed from the handler
if the counter didn't overflow based on the counter value.
Second, this change makes sure that whenever the counter is read,
it's value is updated to reflect the latest count.
Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
target/riscv/csr.c | 5 ++++-
target/riscv/pmu.c | 30 +++++++++++++++++++++++++++---
target/riscv/pmu.h | 2 ++
3 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index ff06276192dd..8690a7c4c472 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1039,6 +1039,9 @@ static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env,
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 += counter_arr[PRV_M];
}
@@ -1122,7 +1125,7 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
-static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
+RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
bool upper_half, uint32_t ctr_idx)
{
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index 63420d9f3679..a4729f6c53bb 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -425,6 +425,8 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
target_ulong *mhpmevent_val;
uint64_t of_bit_mask;
int64_t irq_trigger_at;
+ uint64_t curr_ctr_val, curr_ctrh_val;
+ uint64_t ctr_val;
if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES &&
evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) {
@@ -454,6 +456,26 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
return;
}
+ riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctr_val, false, ctr_idx);
+ ctr_val = counter->mhpmcounter_val;
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctrh_val, true, ctr_idx);
+ curr_ctr_val = curr_ctr_val | (curr_ctrh_val << 32);
+ ctr_val = ctr_val |
+ ((uint64_t)counter->mhpmcounterh_val << 32);
+ }
+
+ /*
+ * We can not accommodate for inhibited modes when setting up timer. Check
+ * if the counter has actually overflowed or not by comparing current
+ * counter value (accommodated for inhibited modes) with software written
+ * counter value.
+ */
+ if (curr_ctr_val >= ctr_val) {
+ riscv_pmu_setup_timer(env, curr_ctr_val, ctr_idx);
+ return;
+ }
+
if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
/* Generate interrupt only if OF bit is clear */
if (!(*mhpmevent_val & of_bit_mask)) {
@@ -475,7 +497,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;
+ uint64_t overflow_delta, overflow_at, curr_ns;
int64_t overflow_ns, overflow_left = 0;
RISCVCPU *cpu = env_archcpu(env);
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
@@ -506,8 +528,10 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
} else {
return -1;
}
- overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
- overflow_ns;
+ curr_ns = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ overflow_at = curr_ns + overflow_ns;
+ if (overflow_at <= curr_ns)
+ overflow_at = UINT64_MAX;
if (overflow_at > INT64_MAX) {
overflow_left += overflow_at - INT64_MAX;
diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index ca40cfeed647..3853d0e2629e 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -36,5 +36,7 @@ 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);
#endif /* RISCV_PMU_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 12/13] target/riscv: Do not setup pmu timer if OF is disabled
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (10 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 11/13] target/riscv: More accurately model priv mode filtering Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-11 22:31 ` [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config Atish Patra
2024-07-15 1:01 ` [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Alistair Francis
13 siblings, 0 replies; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
The timer is setup function is invoked in both hpmcounter
write and mcountinhibit write path. If the OF bit set, the
LCOFI interrupt is disabled. There is no benefitting in
setting up the qemu timer until LCOFI is cleared to indicate
that interrupts can be fired again.
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/pmu.c | 56 ++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index a4729f6c53bb..3cc0b3648cad 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -416,14 +416,49 @@ int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value,
return 0;
}
+static bool pmu_hpmevent_is_of_set(CPURISCVState *env, uint32_t ctr_idx)
+{
+ target_ulong mhpmevent_val;
+ uint64_t of_bit_mask;
+
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ mhpmevent_val = env->mhpmeventh_val[ctr_idx];
+ of_bit_mask = MHPMEVENTH_BIT_OF;
+ } else {
+ mhpmevent_val = env->mhpmevent_val[ctr_idx];
+ of_bit_mask = MHPMEVENT_BIT_OF;
+ }
+
+ return get_field(mhpmevent_val, of_bit_mask);
+}
+
+static bool pmu_hpmevent_set_of_if_clear(CPURISCVState *env, uint32_t ctr_idx)
+{
+ target_ulong *mhpmevent_val;
+ uint64_t of_bit_mask;
+
+ if (riscv_cpu_mxl(env) == MXL_RV32) {
+ mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
+ of_bit_mask = MHPMEVENTH_BIT_OF;
+ } else {
+ mhpmevent_val = &env->mhpmevent_val[ctr_idx];
+ of_bit_mask = MHPMEVENT_BIT_OF;
+ }
+
+ if (!get_field(*mhpmevent_val, of_bit_mask)) {
+ *mhpmevent_val |= of_bit_mask;
+ return true;
+ }
+
+ return false;
+}
+
static void pmu_timer_trigger_irq(RISCVCPU *cpu,
enum riscv_pmu_event_idx evt_idx)
{
uint32_t ctr_idx;
CPURISCVState *env = &cpu->env;
PMUCTRState *counter;
- target_ulong *mhpmevent_val;
- uint64_t of_bit_mask;
int64_t irq_trigger_at;
uint64_t curr_ctr_val, curr_ctrh_val;
uint64_t ctr_val;
@@ -439,12 +474,9 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
return;
}
- if (riscv_cpu_mxl(env) == MXL_RV32) {
- mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
- of_bit_mask = MHPMEVENTH_BIT_OF;
- } else {
- mhpmevent_val = &env->mhpmevent_val[ctr_idx];
- of_bit_mask = MHPMEVENT_BIT_OF;
+ /* Generate interrupt only if OF bit is clear */
+ if (pmu_hpmevent_is_of_set(env, ctr_idx)) {
+ return;
}
counter = &env->pmu_ctrs[ctr_idx];
@@ -477,9 +509,7 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
}
if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
- /* Generate interrupt only if OF bit is clear */
- if (!(*mhpmevent_val & of_bit_mask)) {
- *mhpmevent_val |= of_bit_mask;
+ if (pmu_hpmevent_set_of_if_clear(env, ctr_idx)) {
riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
}
}
@@ -502,7 +532,9 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
RISCVCPU *cpu = env_archcpu(env);
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
- if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) {
+ /* No need to setup a timer if LCOFI is disabled when OF is set */
+ if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf ||
+ pmu_hpmevent_is_of_set(env, ctr_idx)) {
return -1;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (11 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 12/13] target/riscv: Do not setup pmu timer if OF is disabled Atish Patra
@ 2024-07-11 22:31 ` Atish Patra
2024-07-15 0:53 ` Alistair Francis
2024-07-15 1:01 ` [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Alistair Francis
13 siblings, 1 reply; 19+ messages in thread
From: Atish Patra @ 2024-07-11 22:31 UTC (permalink / raw)
To: qemu-riscv, qemu-devel
Cc: palmer, liwei1518, zhiwei_liu, bin.meng, dbarboza,
alistair.francis
Create a new config for Smcntrpmf extension so that it can be enabled/
disabled from the qemu commandline.
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
target/riscv/cpu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 63f553c92b00..ef50130a91e7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1468,6 +1468,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
/* Defaults for standard extensions */
MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
+ MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false),
MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
--
2.34.1
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties
2024-07-11 22:31 ` [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties Atish Patra
@ 2024-07-15 0:42 ` Alistair Francis
0 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2024-07-15 0:42 UTC (permalink / raw)
To: Atish Patra
Cc: qemu-riscv, qemu-devel, palmer, liwei1518, zhiwei_liu, bin.meng,
dbarboza, alistair.francis
On Fri, Jul 12, 2024 at 8:33 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> From: Kaiwen Xue <kaiwenx@rivosinc.com>
>
> This adds the properties for ISA extension smcntrpmf. Patches
> implementing it will follow.
>
> Signed-off-by: Kaiwen Xue <kaiwenx@rivosinc.com>
> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu.c | 1 +
> target/riscv/cpu_cfg.h | 1 +
> 2 files changed, 2 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 4760cb2cc17f..63f553c92b00 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
> ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
> ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
> ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
> + ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
> ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
> ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
> ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index fb7eebde523b..b1376beb1dab 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -74,6 +74,7 @@ struct RISCVCPUConfig {
> bool ext_ztso;
> bool ext_smstateen;
> bool ext_sstc;
> + bool ext_smcntrpmf;
> bool ext_svadu;
> bool ext_svinval;
> bool ext_svnapot;
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support
2024-07-11 22:31 ` [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support Atish Patra
@ 2024-07-15 0:46 ` Alistair Francis
0 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2024-07-15 0:46 UTC (permalink / raw)
To: Atish Patra
Cc: qemu-riscv, qemu-devel, palmer, liwei1518, zhiwei_liu, bin.meng,
dbarboza, alistair.francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> From: Kaiwen Xue <kaiwenx@rivosinc.com>
>
> QEMU only calculates dummy cycles and instructions, so there is no
> actual means to stop the icount in QEMU. Hence this patch merely adds
> the functionality of accessing the cfg registers, and cause no actual
> effects on the counting of cycle and instret counters.
>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> Signed-off-by: Kaiwen Xue <kaiwenx@rivosinc.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu_bits.h | 12 +++++
> target/riscv/csr.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 149 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 5faa817453bb..32b068f18aa5 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -926,6 +926,18 @@ typedef enum RISCVException {
> #define MHPMEVENT_BIT_VUINH BIT_ULL(58)
> #define MHPMEVENTH_BIT_VUINH BIT(26)
>
> +#define MHPMEVENT_FILTER_MASK (MHPMEVENT_BIT_MINH | \
> + MHPMEVENT_BIT_SINH | \
> + MHPMEVENT_BIT_UINH | \
> + MHPMEVENT_BIT_VSINH | \
> + MHPMEVENT_BIT_VUINH)
> +
> +#define MHPMEVENTH_FILTER_MASK (MHPMEVENTH_BIT_MINH | \
> + MHPMEVENTH_BIT_SINH | \
> + MHPMEVENTH_BIT_UINH | \
> + MHPMEVENTH_BIT_VSINH | \
> + MHPMEVENTH_BIT_VUINH)
> +
> #define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000)
> #define MHPMEVENT_IDX_MASK 0xFFFFF
> #define MHPMEVENT_SSCOF_RESVD 16
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 3ad851707e5c..b814d176cbb8 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -30,7 +30,6 @@
> #include "qemu/guest-random.h"
> #include "qapi/error.h"
>
> -
> /* CSR function table public API */
> void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
> {
> @@ -236,6 +235,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, int csrno)
> return sscofpmf(env, csrno);
> }
>
> +static RISCVException smcntrpmf(CPURISCVState *env, int csrno)
> +{
> + if (!riscv_cpu_cfg(env)->ext_smcntrpmf) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno)
> +{
> + if (riscv_cpu_mxl(env) != MXL_RV32) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + return smcntrpmf(env, csrno);
> +}
> +
> static RISCVException any(CPURISCVState *env, int csrno)
> {
> return RISCV_EXCP_NONE;
> @@ -830,6 +847,111 @@ static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
>
> #else /* CONFIG_USER_ONLY */
>
> +static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->mcyclecfg;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> + uint64_t inh_avail_mask;
> +
> + if (riscv_cpu_mxl(env) == MXL_RV32) {
> + env->mcyclecfg = val;
> + } else {
> + /* Set xINH fields if priv mode supported */
> + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MCYCLECFG_BIT_MINH;
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFG_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFG_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MCYCLECFG_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MCYCLECFG_BIT_VSINH : 0;
> + env->mcyclecfg = val & inh_avail_mask;
> + }
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->mcyclecfgh;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
> + MCYCLECFGH_BIT_MINH);
> +
> + /* Set xINH fields if priv mode supported */
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFGH_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFGH_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MCYCLECFGH_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MCYCLECFGH_BIT_VSINH : 0;
> +
> + env->mcyclecfgh = val & inh_avail_mask;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_minstretcfg(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->minstretcfg;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_minstretcfg(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> + uint64_t inh_avail_mask;
> +
> + if (riscv_cpu_mxl(env) == MXL_RV32) {
> + env->minstretcfg = val;
> + } else {
> + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MINSTRETCFG_BIT_MINH;
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFG_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFG_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MINSTRETCFG_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MINSTRETCFG_BIT_VSINH : 0;
> + env->minstretcfg = val & inh_avail_mask;
> + }
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_minstretcfgh(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->minstretcfgh;
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_minstretcfgh(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
> + MINSTRETCFGH_BIT_MINH);
> +
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFGH_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFGH_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MINSTRETCFGH_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MINSTRETCFGH_BIT_VSINH : 0;
> +
> + env->minstretcfgh = val & inh_avail_mask;
> + return RISCV_EXCP_NONE;
> +}
> +
> static RISCVException read_mhpmevent(CPURISCVState *env, int csrno,
> target_ulong *val)
> {
> @@ -5051,6 +5173,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> write_mcountinhibit,
> .min_priv_ver = PRIV_VERSION_1_11_0 },
>
> + [CSR_MCYCLECFG] = { "mcyclecfg", smcntrpmf, read_mcyclecfg,
> + write_mcyclecfg,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MINSTRETCFG] = { "minstretcfg", smcntrpmf, read_minstretcfg,
> + write_minstretcfg,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> +
> [CSR_MHPMEVENT3] = { "mhpmevent3", any, read_mhpmevent,
> write_mhpmevent },
> [CSR_MHPMEVENT4] = { "mhpmevent4", any, read_mhpmevent,
> @@ -5110,6 +5239,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent,
> write_mhpmevent },
>
> + [CSR_MCYCLECFGH] = { "mcyclecfgh", smcntrpmf_32, read_mcyclecfgh,
> + write_mcyclecfgh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MINSTRETCFGH] = { "minstretcfgh", smcntrpmf_32, read_minstretcfgh,
> + write_minstretcfgh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> +
> [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf_32, read_mhpmeventh,
> write_mhpmeventh,
> .min_priv_ver = PRIV_VERSION_1_12_0 },
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available
2024-07-11 22:31 ` [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available Atish Patra
@ 2024-07-15 0:49 ` Alistair Francis
0 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2024-07-15 0:49 UTC (permalink / raw)
To: Atish Patra
Cc: qemu-riscv, qemu-devel, palmer, liwei1518, zhiwei_liu, bin.meng,
dbarboza, alistair.francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> Currently, the INH fields are set in mhpmevent uncoditionally
> without checking if a particular priv mode is supported or not.
>
> Suggested-by: Alistair Francis <alistair23@gmail.com>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
Thanks!
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/csr.c | 29 +++++++++++++++++++++++++----
> 1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index b814d176cbb8..121996edab4b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -967,13 +967,24 @@ static RISCVException write_mhpmevent(CPURISCVState *env, int csrno,
> {
> int evt_index = csrno - CSR_MCOUNTINHIBIT;
> uint64_t mhpmevt_val = val;
> -
> - env->mhpmevent_val[evt_index] = val;
> + uint64_t inh_avail_mask;
>
> if (riscv_cpu_mxl(env) == MXL_RV32) {
> + env->mhpmevent_val[evt_index] = val;
> mhpmevt_val = mhpmevt_val |
> ((uint64_t)env->mhpmeventh_val[evt_index] << 32);
> + } else {
> + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH;
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENT_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH : 0;
> + mhpmevt_val = val & inh_avail_mask;
> + env->mhpmevent_val[evt_index] = mhpmevt_val;
> }
> +
> riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
>
> return RISCV_EXCP_NONE;
> @@ -993,11 +1004,21 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno,
> target_ulong val)
> {
> int evt_index = csrno - CSR_MHPMEVENT3H + 3;
> - uint64_t mhpmevth_val = val;
> + uint64_t mhpmevth_val;
> uint64_t mhpmevt_val = env->mhpmevent_val[evt_index];
> + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
> + MHPMEVENTH_BIT_MINH);
> +
> + inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0;
> + inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0;
> + inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> + riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0;
>
> + mhpmevth_val = val & inh_avail_mask;
> mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32);
> - env->mhpmeventh_val[evt_index] = val;
> + env->mhpmeventh_val[evt_index] = mhpmevth_val;
>
> riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
>
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config
2024-07-11 22:31 ` [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config Atish Patra
@ 2024-07-15 0:53 ` Alistair Francis
0 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2024-07-15 0:53 UTC (permalink / raw)
To: Atish Patra
Cc: qemu-riscv, qemu-devel, palmer, liwei1518, zhiwei_liu, bin.meng,
dbarboza, alistair.francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> Create a new config for Smcntrpmf extension so that it can be enabled/
> disabled from the qemu commandline.
>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 63f553c92b00..ef50130a91e7 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1468,6 +1468,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
> const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
> /* Defaults for standard extensions */
> MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
> + MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false),
> MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
> MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
> MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
>
> --
> 2.34.1
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
` (12 preceding siblings ...)
2024-07-11 22:31 ` [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config Atish Patra
@ 2024-07-15 1:01 ` Alistair Francis
13 siblings, 0 replies; 19+ messages in thread
From: Alistair Francis @ 2024-07-15 1:01 UTC (permalink / raw)
To: Atish Patra
Cc: qemu-riscv, qemu-devel, palmer, liwei1518, zhiwei_liu, bin.meng,
dbarboza, alistair.francis
On Fri, Jul 12, 2024 at 8:33 AM Atish Patra <atishp@rivosinc.com> wrote:
>
> This patch series adds the support for RISC-V ISA extension smcntrpmf (cycle and
> privilege mode filtering) [1]. It is based on Kevin's earlier work but improves
> it by actually implement privilege mode filtering by tracking the privilege
> mode switches. This enables the privilege mode filtering for mhpmcounters as
> well. However, Smcntrpmf/Sscofpmf must be enabled to leverage this.
>
> The series is also available at [2] as well.
>
> Changes in v8:
> - Moved the config option to a separate patch at the end of the series.
> - Fixed a comments recieved in v7 around setting INH bit based on available priv modes.
> - Updated the RB/AB tags.
> - Link to v7: https://lore.kernel.org/r/20240626-smcntrpmf_v7-v7-0-bb0f10af7fa9@rivosinc.com
>
> Changes from v6->v7:
> 1. Fixed a compilation issue.
>
> Changes from v5->v6:
> 1. Rebased on top of alister/riscv-to-apply.next (c50aabe132) and icount fix
> patch[4] which may cause conflicts.
> 2. Fixed a bug in pmf logic related to VS<->HS transition and same mode
> recording.
> 3. Merged assorted fixes PR as the changes are intertwined. [2]
> 4. Fix counter inhibit CSR behavior. This change now start counters from both
> mhpmcounter and mcountinhibit writes. Previously cycle/inst timer was
> only started on mhpmcounterx write.
> 5. Optimized the PMU timer setup code.
>
> Changes from v4->v5:
> 1. Rebased on top of master(158a054c4d1a).
> 2. Fixed a bug for VS<->HS transition.
>
> Changes from v3->v4:
> 1. Fixed the ordering of the ISA extension names in isa_edata_arr.
> 2. Added RB tags.
>
> Changes from v2->v3:
> 1. Fixed the rebasing error in PATCH2.
> 2. Added RB tags.
> 3. Addressed other review comments.
>
> Changes from v1->v2:
> 1. Implemented actual mode filtering for both icount and host ticks mode.
> 1. Addressed comments in v1.
> 2. Added Kevin's personal email address.
>
> [1] https://github.com/riscv/riscv-smcntrpmf
> [2] https://github.com/atishp04/qemu/tree/b4/smcntrpmf_v7
> [3] https://lore.kernel.org/all/20240429-countinhibit_fix-v1-0-802ec1e99133@rivosinc.com/
> [4] https://lore.kernel.org/qemu-riscv/20240618112649.76683-1-cleger@rivosinc.com/
>
> Cc: Rajnesh Kanwal <rkanwal@rivosinc.com>
>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
> ---
> Atish Patra (7):
> target/riscv: Fix the predicate functions for mhpmeventhX CSRs
> target/riscv: Only set INH fields if priv mode is available
> target/riscv: Implement privilege mode filtering for cycle/instret
> target/riscv: Save counter values during countinhibit update
> target/riscv: Enforce WARL behavior for scounteren/hcounteren
> target/riscv: Do not setup pmu timer if OF is disabled
> target/riscv: Expose the Smcntrpmf config
>
> Kaiwen Xue (3):
> target/riscv: Add cycle & instret privilege mode filtering properties
> target/riscv: Add cycle & instret privilege mode filtering definitions
> target/riscv: Add cycle & instret privilege mode filtering support
>
> Rajnesh Kanwal (3):
> target/riscv: Combine set_mode and set_virt functions.
> target/riscv: Start counters from both mhpmcounter and mcountinhibit
> target/riscv: More accurately model priv mode filtering.
>
> target/riscv/cpu.c | 2 +
> target/riscv/cpu.h | 20 ++-
> target/riscv/cpu_bits.h | 41 +++++
> target/riscv/cpu_cfg.h | 1 +
> target/riscv/cpu_helper.c | 66 +++----
> target/riscv/csr.c | 437 +++++++++++++++++++++++++++++++++++++---------
> target/riscv/machine.c | 5 +-
> target/riscv/op_helper.c | 17 +-
> target/riscv/pmu.c | 181 +++++++++++++++++--
> target/riscv/pmu.h | 4 +
> 10 files changed, 624 insertions(+), 150 deletions(-)
Thanks!
Applied to riscv-to-apply.next
Alistair
> ---
> base-commit: 842a3d79a0e37cd3d685c4728308fac0d9bfd0bb
> change-id: 20240626-smcntrpmf_v7-3b275d1da117
> --
> Regards,
> Atish patra
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2024-07-15 1:03 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-11 22:31 [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Atish Patra
2024-07-11 22:31 ` [PATCH v8 01/13] target/riscv: Combine set_mode and set_virt functions Atish Patra
2024-07-11 22:31 ` [PATCH v8 02/13] target/riscv: Fix the predicate functions for mhpmeventhX CSRs Atish Patra
2024-07-11 22:31 ` [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties Atish Patra
2024-07-15 0:42 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 04/13] target/riscv: Add cycle & instret privilege mode filtering definitions Atish Patra
2024-07-11 22:31 ` [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support Atish Patra
2024-07-15 0:46 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available Atish Patra
2024-07-15 0:49 ` Alistair Francis
2024-07-11 22:31 ` [PATCH v8 07/13] target/riscv: Implement privilege mode filtering for cycle/instret Atish Patra
2024-07-11 22:31 ` [PATCH v8 08/13] target/riscv: Save counter values during countinhibit update Atish Patra
2024-07-11 22:31 ` [PATCH v8 09/13] target/riscv: Enforce WARL behavior for scounteren/hcounteren Atish Patra
2024-07-11 22:31 ` [PATCH v8 10/13] target/riscv: Start counters from both mhpmcounter and mcountinhibit Atish Patra
2024-07-11 22:31 ` [PATCH v8 11/13] target/riscv: More accurately model priv mode filtering Atish Patra
2024-07-11 22:31 ` [PATCH v8 12/13] target/riscv: Do not setup pmu timer if OF is disabled Atish Patra
2024-07-11 22:31 ` [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config Atish Patra
2024-07-15 0:53 ` Alistair Francis
2024-07-15 1:01 ` [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support Alistair Francis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).