Skip to content

Commit

Permalink
target/ppc: PMU: update counters on PMCs r/w
Browse files Browse the repository at this point in the history
Calling pmu_update_cycles() on every PMC read/write operation ensures
that the values being fetched are up to date with the current PMU state.

In theory we can get away by just trapping PMCs reads, but we're going
to trap PMC writes to deal with counter overflow logic later on.  Let's
put the required wiring for that and make our lives a bit easier in the
next patches.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20211201151734.654994-4-danielhb413@gmail.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
danielhb authored and legoater committed Dec 17, 2021
1 parent c2eff58 commit 308b9fa
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 8 deletions.
12 changes: 6 additions & 6 deletions target/ppc/cpu_init.c
Expand Up @@ -6266,27 +6266,27 @@ static void register_book3s_pmu_sup_sprs(CPUPPCState *env)
KVM_REG_PPC_MMCRA, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC1, "PMC1",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC1, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC2, "PMC2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC2, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC3, "PMC3",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC3, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC4, "PMC4",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC4, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC5, "PMC5",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC5, 0x00000000);
spr_register_kvm(env, SPR_POWER_PMC6, "PMC6",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
&spr_read_PMC, &spr_write_PMC,
KVM_REG_PPC_PMC6, 0x00000000);
spr_register_kvm(env, SPR_POWER_SIAR, "SIAR",
SPR_NOACCESS, SPR_NOACCESS,
Expand Down
2 changes: 2 additions & 0 deletions target/ppc/helper.h
Expand Up @@ -21,6 +21,8 @@ DEF_HELPER_1(hrfid, void, env)
DEF_HELPER_2(store_lpcr, void, env, tl)
DEF_HELPER_2(store_pcr, void, env, tl)
DEF_HELPER_2(store_mmcr0, void, env, tl)
DEF_HELPER_3(store_pmc, void, env, i32, i64)
DEF_HELPER_2(read_pmc, tl, env, i32)
#endif
DEF_HELPER_1(check_tlb_flush_local, void, env)
DEF_HELPER_1(check_tlb_flush_global, void, env)
Expand Down
29 changes: 27 additions & 2 deletions target/ppc/power8-pmu-regs.c.inc
Expand Up @@ -181,13 +181,23 @@ void spr_write_MMCR2_ureg(DisasContext *ctx, int sprn, int gprn)
tcg_temp_free(masked_gprn);
}

void spr_read_PMC(DisasContext *ctx, int gprn, int sprn)
{
TCGv_i32 t_sprn = tcg_const_i32(sprn);

gen_icount_io_start(ctx);
gen_helper_read_pmc(cpu_gpr[gprn], cpu_env, t_sprn);

tcg_temp_free_i32(t_sprn);
}

void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn)
{
if (!spr_groupA_read_allowed(ctx)) {
return;
}

spr_read_ureg(ctx, gprn, sprn);
spr_read_PMC(ctx, gprn, sprn + 0x10);
}

void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
Expand All @@ -206,13 +216,23 @@ void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn)
spr_read_PMC14_ureg(ctx, gprn, sprn);
}

void spr_write_PMC(DisasContext *ctx, int sprn, int gprn)
{
TCGv_i32 t_sprn = tcg_const_i32(sprn);

gen_icount_io_start(ctx);
gen_helper_store_pmc(cpu_env, t_sprn, cpu_gpr[gprn]);

tcg_temp_free_i32(t_sprn);
}

void spr_write_PMC14_ureg(DisasContext *ctx, int sprn, int gprn)
{
if (!spr_groupA_write_allowed(ctx)) {
return;
}

spr_write_ureg(ctx, sprn, gprn);
spr_write_PMC(ctx, sprn + 0x10, gprn);
}

void spr_write_PMC56_ureg(DisasContext *ctx, int sprn, int gprn)
Expand Down Expand Up @@ -280,4 +300,9 @@ void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
{
spr_write_generic(ctx, sprn, gprn);
}

void spr_write_PMC(DisasContext *ctx, int sprn, int gprn)
{
spr_write_generic(ctx, sprn, gprn);
}
#endif /* defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) */
14 changes: 14 additions & 0 deletions target/ppc/power8-pmu.c
Expand Up @@ -133,6 +133,20 @@ void helper_store_mmcr0(CPUPPCState *env, target_ulong value)
hreg_compute_hflags(env);
}

target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn)
{
pmu_update_cycles(env);

return env->spr[sprn];
}

void helper_store_pmc(CPUPPCState *env, uint32_t sprn, uint64_t value)
{
pmu_update_cycles(env);

env->spr[sprn] = value;
}

static void fire_PMC_interrupt(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
Expand Down
2 changes: 2 additions & 0 deletions target/ppc/spr_tcg.h
Expand Up @@ -26,6 +26,7 @@ void spr_noaccess(DisasContext *ctx, int gprn, int sprn);
void spr_read_generic(DisasContext *ctx, int gprn, int sprn);
void spr_write_generic(DisasContext *ctx, int sprn, int gprn);
void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn);
void spr_write_PMC(DisasContext *ctx, int sprn, int gprn);
void spr_read_xer(DisasContext *ctx, int gprn, int sprn);
void spr_write_xer(DisasContext *ctx, int sprn, int gprn);
void spr_read_lr(DisasContext *ctx, int gprn, int sprn);
Expand All @@ -35,6 +36,7 @@ void spr_write_ctr(DisasContext *ctx, int sprn, int gprn);
void spr_read_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_MMCR0_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_MMCR2_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_PMC(DisasContext *ctx, int gprn, int sprn);
void spr_read_PMC14_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_PMC56_ureg(DisasContext *ctx, int gprn, int sprn);
void spr_read_tbl(DisasContext *ctx, int gprn, int sprn);
Expand Down

0 comments on commit 308b9fa

Please sign in to comment.