target/ppc: Work [S]PURR implementation and add HV support
The Processor Utilisation of Resources Register (PURR) and Scaled Processor Utilisation of Resources Register (SPURR) provide an estimate of the resources used by the thread, present on POWER7 and later processors. Currently the [S]PURR registers simply count at the rate of the timebase. Preserve this behaviour but rework the implementation to store an offset like the timebase rather than doing the calculation manually. Also allow hypervisor write access to the register along with the currently available read access. Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> [ clg: rebased on current ppc tree ] Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20191128134700.16091-3-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
5d62725b2f
commit
5cc7e69f6d
17
hw/ppc/ppc.c
17
hw/ppc/ppc.c
@ -809,12 +809,9 @@ target_ulong cpu_ppc_load_hdecr(CPUPPCState *env)
|
||||
uint64_t cpu_ppc_load_purr (CPUPPCState *env)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
uint64_t diff;
|
||||
|
||||
diff = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - tb_env->purr_start;
|
||||
|
||||
return tb_env->purr_load +
|
||||
muldiv64(diff, tb_env->tb_freq, NANOSECONDS_PER_SECOND);
|
||||
return cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
|
||||
tb_env->purr_offset);
|
||||
}
|
||||
|
||||
/* When decrementer expires,
|
||||
@ -973,12 +970,12 @@ static void cpu_ppc_hdecr_cb(void *opaque)
|
||||
cpu_ppc_hdecr_excp(cpu);
|
||||
}
|
||||
|
||||
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
||||
void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
|
||||
{
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
|
||||
tb_env->purr_load = value;
|
||||
tb_env->purr_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
|
||||
&tb_env->purr_offset, value);
|
||||
}
|
||||
|
||||
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
||||
@ -995,7 +992,7 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
||||
*/
|
||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
|
||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
|
||||
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
||||
cpu_ppc_store_purr(env, 0x0000000000000000ULL);
|
||||
}
|
||||
|
||||
static void timebase_save(PPCTimebase *tb)
|
||||
|
@ -33,8 +33,7 @@ struct ppc_tb_t {
|
||||
/* Hypervisor decrementer management */
|
||||
uint64_t hdecr_next; /* Tick for next hdecr interrupt */
|
||||
QEMUTimer *hdecr_timer;
|
||||
uint64_t purr_load;
|
||||
uint64_t purr_start;
|
||||
int64_t purr_offset;
|
||||
void *opaque;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
@ -1311,6 +1311,7 @@ void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value);
|
||||
target_ulong cpu_ppc_load_hdecr(CPUPPCState *env);
|
||||
void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
|
||||
uint64_t cpu_ppc_load_purr(CPUPPCState *env);
|
||||
void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value);
|
||||
uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env);
|
||||
uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
@ -655,6 +655,7 @@ DEF_HELPER_FLAGS_1(load_601_rtcu, TCG_CALL_NO_RWG, tl, env)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_FLAGS_1(load_purr, TCG_CALL_NO_RWG, tl, env)
|
||||
DEF_HELPER_FLAGS_2(store_purr, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_2(store_ptcr, void, env, tl)
|
||||
#endif
|
||||
DEF_HELPER_2(store_sdr1, void, env, tl)
|
||||
|
@ -55,6 +55,11 @@ target_ulong helper_load_purr(CPUPPCState *env)
|
||||
{
|
||||
return (target_ulong)cpu_ppc_load_purr(env);
|
||||
}
|
||||
|
||||
void helper_store_purr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
cpu_ppc_store_purr(env, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
target_ulong helper_load_601_rtcl(CPUPPCState *env)
|
||||
|
@ -287,6 +287,11 @@ static void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
|
||||
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
|
||||
}
|
||||
|
||||
static void spr_write_purr(DisasContext *ctx, int sprn, int gprn)
|
||||
{
|
||||
gen_helper_store_purr(cpu_env, cpu_gpr[gprn]);
|
||||
}
|
||||
|
||||
/* HDECR */
|
||||
static void spr_read_hdecr(DisasContext *ctx, int gprn, int sprn)
|
||||
{
|
||||
@ -8013,14 +8018,16 @@ static void gen_spr_book3s_purr(CPUPPCState *env)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* PURR & SPURR: Hack - treat these as aliases for the TB for now */
|
||||
spr_register_kvm(env, SPR_PURR, "PURR",
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
KVM_REG_PPC_PURR, 0x00000000);
|
||||
spr_register_kvm(env, SPR_SPURR, "SPURR",
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
KVM_REG_PPC_SPURR, 0x00000000);
|
||||
spr_register_kvm_hv(env, SPR_PURR, "PURR",
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, &spr_write_purr,
|
||||
KVM_REG_PPC_PURR, 0x00000000);
|
||||
spr_register_kvm_hv(env, SPR_SPURR, "SPURR",
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, SPR_NOACCESS,
|
||||
&spr_read_purr, &spr_write_purr,
|
||||
KVM_REG_PPC_SPURR, 0x00000000);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user