Structure CPUTimerState is added here, QEMUTimer and IRQ number is included, also the CPUSysState pointer is in this structure, so it is easy to add another separate timer in guest mode.
Signed-off-by: Bibo Mao <[email protected]> --- target/loongarch/cpu.c | 10 ++++++++-- target/loongarch/cpu.h | 14 +++++++++++++- target/loongarch/internals.h | 6 +++--- target/loongarch/tcg/csr_helper.c | 7 ++----- target/loongarch/tcg/op_helper.c | 3 +-- target/loongarch/tcg/timer.c | 27 ++++++++++++--------------- 6 files changed, 39 insertions(+), 28 deletions(-) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index cba227fd1b..7182b85058 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -758,11 +758,17 @@ static void loongarch_cpu_init(Object *obj) { #ifndef CONFIG_USER_ONLY LoongArchCPU *cpu = LOONGARCH_CPU(obj); + CPULoongArchState *env = &cpu->env; + CPUTimerState *timer; 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->sys_state = &env->sys_states[0]; + 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 97db3b453f..0d7679f3be 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -382,6 +382,13 @@ typedef struct CPUSysState { uint64_t CSR_MSGIE; } CPUSysState; +typedef struct CPUTimerState { + QEMUTimer timer; + int irq; + CPUState *cs; + CPUSysState *sys_state; +} CPUTimerState; + typedef struct CPUArchState { uint64_t gpr[32]; uint64_t pc; @@ -418,6 +425,7 @@ typedef struct CPUArchState { AddressSpace *address_space_iocsr; uint32_t mp_state; + CPUTimerState timer_states[1]; #endif CPUSysState *sys_state; } CPULoongArchState; @@ -438,7 +446,6 @@ struct ArchCPU { CPUState parent_obj; CPULoongArchState env; - QEMUTimer timer; uint32_t phy_id; OnOffAuto lbt; OnOffAuto pmu; @@ -496,6 +503,11 @@ static inline void set_sys_state(CPULoongArchState *env, CPUSysState *sys) env->sys_state = sys; } +static inline CPUTimerState *env_timer(CPULoongArchState *env) +{ + return &env->timer_states[0]; +} + 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..bc6511a6f0 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,11 +133,10 @@ 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); int64_t old_v = sys->CSR_TCFG; - cpu_loongarch_set_timer_config(cpu, val); + cpu_loongarch_set_timer_config(env_timer(env), val); return old_v; } diff --git a/target/loongarch/tcg/op_helper.c b/target/loongarch/tcg/op_helper.c index c090d5b12e..76d7201aea 100644 --- a/target/loongarch/tcg/op_helper.c +++ b/target/loongarch/tcg/op_helper.c @@ -73,7 +73,6 @@ 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); plv = FIELD_EX64(sys->CSR_CRMD, CSR_CRMD, PLV); @@ -81,7 +80,7 @@ uint64_t helper_rdtime_d(CPULoongArchState *env) do_raise_exception(env, EXCCODE_IPE, GETPC()); } - return cpu_loongarch_get_timer_counter(cpu); + return cpu_loongarch_get_timer_counter(env_timer(env)); #endif } diff --git a/target/loongarch/tcg/timer.c b/target/loongarch/tcg/timer.c index a25312b9ab..9c5aa6720f 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 = timer->sys_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 = timer->sys_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 = timer->sys_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
