Structure CPUTimerState is added in structure CPUSysState, QEMUTimer and IRQ number is included, so it is easy to add another separate timer if LVZ feature is supported.
Signed-off-by: Bibo Mao <[email protected]> Reviewed-by: Xianglai Li <[email protected]> --- target/loongarch/cpu.c | 11 +++++++++-- target/loongarch/cpu.h | 15 ++++++++++++++- target/loongarch/internals.h | 6 +++--- target/loongarch/tcg/csr_helper.c | 14 ++++++-------- target/loongarch/tcg/op_helper.c | 6 +++--- target/loongarch/tcg/timer.c | 27 ++++++++++++--------------- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index ab37a9e2e6..b8e95750bb 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -727,11 +727,18 @@ static void loongarch_cpu_init(Object *obj) { #ifndef CONFIG_USER_ONLY LoongArchCPU *cpu = LOONGARCH_CPU(obj); +#ifdef CONFIG_TCG + CPULoongArchState *env = &cpu->env; + CPUTimerState *timer; +#endif qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS); #ifdef CONFIG_TCG - timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL, - &cpu_loongarch_timer_cb, cpu); + timer = env_timer(env); + timer->irq = IRQ_TIMER; + timer->cs = CPU(obj); + timer_init_ns(&timer->timer, QEMU_CLOCK_VIRTUAL, + &cpu_loongarch_timer_cb, timer); #endif #endif } diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index d83dcef6f8..c592f69885 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -315,6 +315,12 @@ typedef struct LoongArchBT { uint32_t ftop; } lbt_t; +typedef struct CPUTimerState { + QEMUTimer timer; + int irq; + CPUState *cs; +} CPUTimerState; + #define CPU_VENDOR_LOONGSON "Loongson" #define CPU_MODEL_3A5000 "3A5000" #define CPU_MODEL_1C101 "1C101" @@ -384,6 +390,9 @@ typedef struct CPUSysState { uint64_t CSR_PRCFG1; uint64_t CSR_PRCFG2; uint64_t CSR_PRCFG3; +#ifdef CONFIG_TCG + CPUTimerState timer_state; +#endif } CPUSysState; typedef struct CPUArchState { @@ -446,7 +455,6 @@ struct ArchCPU { CPUState parent_obj; CPULoongArchState env; - QEMUTimer timer; uint32_t phy_id; OnOffAuto lbt; OnOffAuto pmu; @@ -504,6 +512,11 @@ static inline void set_sys_state(CPULoongArchState *env, CPUSysState *sys) env->sys_state = sys; } +static inline CPUTimerState *env_timer(CPULoongArchState *env) +{ + return &env->sys_states[0].timer_state; +} + static inline bool is_la64(CPULoongArchState *env) { return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64; diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index 8c5f095782..f9a0680fe0 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -35,9 +35,9 @@ void loongarch_cpu_update_irq(LoongArchCPU *cpu, uint64_t old); void loongarch_cpu_set_irq(void *opaque, int irq, int level); void cpu_loongarch_timer_cb(void *opaque); -uint64_t cpu_loongarch_get_timer_counter(LoongArchCPU *cpu); -uint64_t cpu_loongarch_get_timer_ticks(LoongArchCPU *cpu); -void cpu_loongarch_set_timer_config(LoongArchCPU *cpu, uint64_t value); +uint64_t cpu_loongarch_get_timer_counter(CPUTimerState *timer); +uint64_t cpu_loongarch_get_timer_ticks(CPUTimerState *timer); +void cpu_loongarch_set_timer_config(CPUTimerState *timer, uint64_t value); bool loongarch_cpu_has_work(CPUState *cs); bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env); #endif /* !CONFIG_USER_ONLY */ diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c index b1a0b005e9..88656b5344 100644 --- a/target/loongarch/tcg/csr_helper.c +++ b/target/loongarch/tcg/csr_helper.c @@ -72,9 +72,7 @@ target_ulong helper_csrrd_cpuid(CPULoongArchState *env) target_ulong helper_csrrd_tval(CPULoongArchState *env) { - LoongArchCPU *cpu = env_archcpu(env); - - return cpu_loongarch_get_timer_ticks(cpu); + return cpu_loongarch_get_timer_ticks(env_timer(env)); } target_ulong helper_csrrd_msgir(CPULoongArchState *env) @@ -135,23 +133,23 @@ target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val) target_ulong helper_csrwr_tcfg(CPULoongArchState *env, target_ulong val) { - LoongArchCPU *cpu = env_archcpu(env); - CPUSysState *sys = env_sys(env); + CPUTimerState *timer = env_timer(env); + CPUSysState *sys = container_of(timer, CPUSysState, timer_state); int64_t old_v = sys->CSR_TCFG; - cpu_loongarch_set_timer_config(cpu, val); + cpu_loongarch_set_timer_config(timer, val); return old_v; } target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val) { - LoongArchCPU *cpu = env_archcpu(env); + CPUTimerState *timer = env_timer(env); int64_t old_v = 0; if (val & 0x1) { bql_lock(); - loongarch_cpu_set_irq(cpu, IRQ_TIMER, 0); + loongarch_cpu_set_irq(LOONGARCH_CPU(timer->cs), timer->irq, 0); bql_unlock(); } return old_v; diff --git a/target/loongarch/tcg/op_helper.c b/target/loongarch/tcg/op_helper.c index c090d5b12e..f98fe4d4a1 100644 --- a/target/loongarch/tcg/op_helper.c +++ b/target/loongarch/tcg/op_helper.c @@ -73,15 +73,15 @@ uint64_t helper_rdtime_d(CPULoongArchState *env) return cpu_get_host_ticks(); #else uint64_t plv; - LoongArchCPU *cpu = env_archcpu(env); - CPUSysState *sys = env_sys(env); + CPUTimerState *timer = env_timer(env); + CPUSysState *sys = container_of(timer, CPUSysState, timer_state); plv = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV); if (extract64(sys->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) { do_raise_exception(env, EXCCODE_IPE, GETPC()); } - return cpu_loongarch_get_timer_counter(cpu); + return cpu_loongarch_get_timer_counter(timer); #endif } diff --git a/target/loongarch/tcg/timer.c b/target/loongarch/tcg/timer.c index a25312b9ab..6a96dfd429 100644 --- a/target/loongarch/tcg/timer.c +++ b/target/loongarch/tcg/timer.c @@ -15,60 +15,57 @@ #define CONSTANT_TIMER_TICK_MASK 0xfffffffffffcUL #define CONSTANT_TIMER_ENABLE 0x1UL -uint64_t cpu_loongarch_get_timer_counter(LoongArchCPU *cpu) +uint64_t cpu_loongarch_get_timer_counter(CPUTimerState *timer) { return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD; } -uint64_t cpu_loongarch_get_timer_ticks(LoongArchCPU *cpu) +uint64_t cpu_loongarch_get_timer_ticks(CPUTimerState *timer) { - CPULoongArchState *env = &cpu->env; - CPUSysState *sys = env_sys(env); + CPUSysState *sys = container_of(timer, CPUSysState, timer_state); uint64_t now, expire; if ((sys->CSR_TCFG & CONSTANT_TIMER_ENABLE) && (sys->CSR_TVAL < sys->CSR_TCFG)) { now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - expire = timer_expire_time_ns(&cpu->timer); + expire = timer_expire_time_ns(&timer->timer); sys->CSR_TVAL = (expire - now) / TIMER_PERIOD; } return sys->CSR_TVAL; } -void cpu_loongarch_set_timer_config(LoongArchCPU *cpu, uint64_t value) +void cpu_loongarch_set_timer_config(CPUTimerState *timer, uint64_t value) { - CPULoongArchState *env = &cpu->env; - CPUSysState *sys = env_sys(env); + CPUSysState *sys = container_of(timer, CPUSysState, timer_state); uint64_t now, next; sys->CSR_TCFG = value; if (value & CONSTANT_TIMER_ENABLE) { now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD; - timer_mod(&cpu->timer, next); + timer_mod(&timer->timer, next); sys->CSR_TVAL = sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK; } else { - timer_del(&cpu->timer); + timer_del(&timer->timer); sys->CSR_TVAL = 0; } } void cpu_loongarch_timer_cb(void *opaque) { - LoongArchCPU *cpu = opaque; - CPULoongArchState *env = &cpu->env; - CPUSysState *sys = env_sys(env); + CPUTimerState *timer = opaque; + CPUSysState *sys = container_of(timer, CPUSysState, timer_state); uint64_t now, next; if (FIELD_EX64(sys->CSR_TCFG, CSR_TCFG, PERIODIC)) { now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); next = now + (sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD; - timer_mod(&cpu->timer, next); + timer_mod(&timer->timer, next); sys->CSR_TVAL = sys->CSR_TCFG & CONSTANT_TIMER_TICK_MASK; } else { sys->CSR_TVAL = CONSTANT_TIMER_TICK_MASK; } - loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1); + loongarch_cpu_set_irq(LOONGARCH_CPU(timer->cs), timer->irq, 1); } -- 2.54.0
