Skip to content

Commit dd4c123

Browse files
atishp04alistair23
authored andcommitted
target/riscv: Do not setup pmu timer if OF is disabled
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> Message-ID: <20240711-smcntrpmf_v7-v8-12-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
1 parent 7411240 commit dd4c123

File tree

1 file changed

+44
-12
lines changed

1 file changed

+44
-12
lines changed

target/riscv/pmu.c

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,49 @@ int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value,
416416
return 0;
417417
}
418418

419+
static bool pmu_hpmevent_is_of_set(CPURISCVState *env, uint32_t ctr_idx)
420+
{
421+
target_ulong mhpmevent_val;
422+
uint64_t of_bit_mask;
423+
424+
if (riscv_cpu_mxl(env) == MXL_RV32) {
425+
mhpmevent_val = env->mhpmeventh_val[ctr_idx];
426+
of_bit_mask = MHPMEVENTH_BIT_OF;
427+
} else {
428+
mhpmevent_val = env->mhpmevent_val[ctr_idx];
429+
of_bit_mask = MHPMEVENT_BIT_OF;
430+
}
431+
432+
return get_field(mhpmevent_val, of_bit_mask);
433+
}
434+
435+
static bool pmu_hpmevent_set_of_if_clear(CPURISCVState *env, uint32_t ctr_idx)
436+
{
437+
target_ulong *mhpmevent_val;
438+
uint64_t of_bit_mask;
439+
440+
if (riscv_cpu_mxl(env) == MXL_RV32) {
441+
mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
442+
of_bit_mask = MHPMEVENTH_BIT_OF;
443+
} else {
444+
mhpmevent_val = &env->mhpmevent_val[ctr_idx];
445+
of_bit_mask = MHPMEVENT_BIT_OF;
446+
}
447+
448+
if (!get_field(*mhpmevent_val, of_bit_mask)) {
449+
*mhpmevent_val |= of_bit_mask;
450+
return true;
451+
}
452+
453+
return false;
454+
}
455+
419456
static void pmu_timer_trigger_irq(RISCVCPU *cpu,
420457
enum riscv_pmu_event_idx evt_idx)
421458
{
422459
uint32_t ctr_idx;
423460
CPURISCVState *env = &cpu->env;
424461
PMUCTRState *counter;
425-
target_ulong *mhpmevent_val;
426-
uint64_t of_bit_mask;
427462
int64_t irq_trigger_at;
428463
uint64_t curr_ctr_val, curr_ctrh_val;
429464
uint64_t ctr_val;
@@ -439,12 +474,9 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
439474
return;
440475
}
441476

442-
if (riscv_cpu_mxl(env) == MXL_RV32) {
443-
mhpmevent_val = &env->mhpmeventh_val[ctr_idx];
444-
of_bit_mask = MHPMEVENTH_BIT_OF;
445-
} else {
446-
mhpmevent_val = &env->mhpmevent_val[ctr_idx];
447-
of_bit_mask = MHPMEVENT_BIT_OF;
477+
/* Generate interrupt only if OF bit is clear */
478+
if (pmu_hpmevent_is_of_set(env, ctr_idx)) {
479+
return;
448480
}
449481

450482
counter = &env->pmu_ctrs[ctr_idx];
@@ -477,9 +509,7 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
477509
}
478510

479511
if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
480-
/* Generate interrupt only if OF bit is clear */
481-
if (!(*mhpmevent_val & of_bit_mask)) {
482-
*mhpmevent_val |= of_bit_mask;
512+
if (pmu_hpmevent_set_of_if_clear(env, ctr_idx)) {
483513
riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
484514
}
485515
}
@@ -502,7 +532,9 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
502532
RISCVCPU *cpu = env_archcpu(env);
503533
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
504534

505-
if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) {
535+
/* No need to setup a timer if LCOFI is disabled when OF is set */
536+
if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf ||
537+
pmu_hpmevent_is_of_set(env, ctr_idx)) {
506538
return -1;
507539
}
508540

0 commit comments

Comments
 (0)