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


Reply via email to