Create clock input for the xtensa CPU device and initialize its frequency to the default core frequency specified in the config.
Signed-off-by: Max Filippov <jcmvb...@gmail.com> --- target/xtensa/cpu.c | 15 +++++++++++++++ target/xtensa/cpu.h | 5 +++++ target/xtensa/op_helper.c | 7 ++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index 224f72323693..fd553fdfb5e6 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -34,6 +34,7 @@ #include "fpu/softfloat.h" #include "qemu/module.h" #include "migration/vmstate.h" +#include "hw/qdev-clock.h" static void xtensa_cpu_set_pc(CPUState *cs, vaddr value) @@ -172,9 +173,23 @@ static void xtensa_cpu_initfn(Object *obj) memory_region_init_io(env->system_er, obj, NULL, env, "er", UINT64_C(0x100000000)); address_space_init(env->address_space_er, env->system_er, "ER"); + + cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0); + clock_set_hz(cpu->clock, env->config->clock_freq_khz * 1000); #endif } +XtensaCPU *xtensa_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk) +{ + DeviceState *cpu; + + cpu = DEVICE(object_new(cpu_type)); + qdev_connect_clock_in(cpu, "clk-in", cpu_refclk); + qdev_realize(cpu, NULL, &error_abort); + + return XTENSA_CPU(cpu); +} + #ifndef CONFIG_USER_ONLY static const VMStateDescription vmstate_xtensa_cpu = { .name = "cpu", diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h index 4515f682aa26..6f773e681384 100644 --- a/target/xtensa/cpu.h +++ b/target/xtensa/cpu.h @@ -30,6 +30,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" +#include "hw/clock.h" #include "xtensa-isa.h" /* Xtensa processors have a weak memory model */ @@ -558,6 +559,7 @@ struct ArchCPU { CPUState parent_obj; /*< public >*/ + Clock *clock; CPUNegativeOffsetState neg; CPUXtensaState env; }; @@ -792,4 +794,7 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc, } } +XtensaCPU *xtensa_cpu_create_with_clock(const char *cpu_type, + Clock *cpu_refclk); + #endif diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c index d85d3516d6a5..1af7becc54b1 100644 --- a/target/xtensa/op_helper.c +++ b/target/xtensa/op_helper.c @@ -38,12 +38,12 @@ void HELPER(update_ccount)(CPUXtensaState *env) { + XtensaCPU *cpu = XTENSA_CPU(env_cpu(env)); uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); env->ccount_time = now; env->sregs[CCOUNT] = env->ccount_base + - (uint32_t)((now - env->time_base) * - env->config->clock_freq_khz / 1000000); + (uint32_t)clock_ns_to_ticks(cpu->clock, now - env->time_base); } void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v) @@ -59,6 +59,7 @@ void HELPER(wsr_ccount)(CPUXtensaState *env, uint32_t v) void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) { + XtensaCPU *cpu = XTENSA_CPU(env_cpu(env)); uint64_t dcc; qatomic_and(&env->sregs[INTSET], @@ -66,7 +67,7 @@ void HELPER(update_ccompare)(CPUXtensaState *env, uint32_t i) HELPER(update_ccount)(env); dcc = (uint64_t)(env->sregs[CCOMPARE + i] - env->sregs[CCOUNT] - 1) + 1; timer_mod(env->ccompare[i].timer, - env->ccount_time + (dcc * 1000000) / env->config->clock_freq_khz); + env->ccount_time + clock_ticks_to_ns(cpu->clock, dcc)); env->yield_needed = 1; } -- 2.30.2