[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 11/31] target/loongarch: Add stabletimer support
From: |
Xiaojuan Yang |
Subject: |
[PATCH 11/31] target/loongarch: Add stabletimer support |
Date: |
Tue, 19 Oct 2021 15:34:57 +0800 |
This patch add a stabletimer support.
Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
target/loongarch/cpu.c | 1 +
target/loongarch/cpu.h | 10 +++++
target/loongarch/csr_helper.c | 26 +++++++++++++
target/loongarch/meson.build | 1 +
target/loongarch/stabletimer.c | 71 ++++++++++++++++++++++++++++++++++
5 files changed, 109 insertions(+)
create mode 100644 target/loongarch/stabletimer.c
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 3e3cf233db..2886dbd642 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -435,6 +435,7 @@ static void set_loongarch_csr(CPULoongArchState *env)
env->CSR_CPUID = (cs->cpu_index & 0x1ff);
env->CSR_EENTRY |= (uint64_t)0x80000000;
env->CSR_TLBRENTRY |= (uint64_t)0x80000000;
+ env->CSR_TMID = cs->cpu_index;
}
#endif
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 182b03fb33..e77517d375 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -46,6 +46,9 @@ FIELD(FCSR0, CAUSE, 24, 5)
extern const char * const regnames[];
extern const char * const fregnames[];
+#define N_IRQS 14
+#define IRQ_TIMER 11
+
#define LOONGARCH_HFLAG_KU 0x00003 /* kernel/user mode mask */
#define LOONGARCH_HFLAG_UM 0x00003 /* user mode flag */
#define LOONGARCH_HFLAG_KM 0x00000 /* kernel mode flag */
@@ -84,6 +87,8 @@ struct CPULoongArchState {
int error_code;
target_ulong exception_base;
#endif
+ void *irq[N_IRQS];
+ QEMUTimer *timer; /* Internal timer */
};
/**
@@ -181,4 +186,9 @@ enum {
#define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
+void cpu_loongarch_clock_init(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env);
+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env);
+void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env,
+ uint64_t value);
#endif /* LOONGARCH_CPU_H */
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
index 9251bfa2a6..6cfb910799 100644
--- a/target/loongarch/csr_helper.c
+++ b/target/loongarch/csr_helper.c
@@ -14,6 +14,7 @@
#include "exec/helper-proto.h"
#include "exec/exec-all.h"
#include "exec/cpu_ldst.h"
+#include "hw/irq.h"
#include "cpu-csr.h"
#include "tcg/tcg-ldst.h"
@@ -78,7 +79,12 @@ target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t
csr)
CASE_CSR_RDQ(KS7)
CASE_CSR_RDQ(KS8)
CASE_CSR_RDQ(TMID)
+ CASE_CSR_RDQ(TCFG)
+ case LOONGARCH_CSR_TVAL:
+ v = cpu_loongarch_get_stable_timer_ticks(env);
+ break;
CASE_CSR_RDQ(CNTC)
+ CASE_CSR_RDQ(TINTCLR)
CASE_CSR_RDQ(LLBCTL)
CASE_CSR_RDQ(IMPCTL1)
CASE_CSR_RDQ(IMPCTL2)
@@ -223,8 +229,16 @@ target_ulong helper_csr_wrq(CPULoongArchState *env,
target_ulong val,
CASE_CSR_WRQ(KS7)
CASE_CSR_WRQ(KS8)
CASE_CSR_WRQ(TMID)
+ case LOONGARCH_CSR_TCFG:
+ old_v = env->CSR_TCFG;
+ cpu_loongarch_store_stable_timer_config(env, val);
+ break;
CASE_CSR_WRQ(TVAL)
CASE_CSR_WRQ(CNTC)
+ case LOONGARCH_CSR_TINTCLR:
+ old_v = 0;
+ qemu_irq_lower(env->irq[IRQ_TIMER]);
+ break;
CASE_CSR_WRQ(LLBCTL)
CASE_CSR_WRQ(IMPCTL1)
CASE_CSR_WRQ(IMPCTL2)
@@ -373,8 +387,12 @@ void helper_csr_xchgq_r0(CPULoongArchState *env,
target_ulong mask, uint64_t csr
CASE_CSR_XCHGQ(KS7)
CASE_CSR_XCHGQ(KS8)
CASE_CSR_XCHGQ(TMID)
+ case LOONGARCH_CSR_TCFG:
+ cpu_loongarch_store_stable_timer_config(env, env->CSR_TCFG & (~mask));
+ break;
CASE_CSR_XCHGQ(TVAL)
CASE_CSR_XCHGQ(CNTC)
+ CASE_CSR_XCHGQ(TINTCLR)
CASE_CSR_XCHGQ(LLBCTL)
CASE_CSR_XCHGQ(IMPCTL1)
CASE_CSR_XCHGQ(IMPCTL2)
@@ -471,6 +489,7 @@ void helper_csr_xchgq_r0(CPULoongArchState *env,
target_ulong mask, uint64_t csr
target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val,
target_ulong mask, uint64_t csr)
{
+ target_ulong tmp;
target_ulong v = val & mask;
#define CASE_CSR_XCHGQ(csr) \
@@ -523,8 +542,15 @@ target_ulong helper_csr_xchgq(CPULoongArchState *env,
target_ulong val,
CASE_CSR_XCHGQ(KS7)
CASE_CSR_XCHGQ(KS8)
CASE_CSR_XCHGQ(TMID)
+ case LOONGARCH_CSR_TCFG:
+ val = env->CSR_TCFG;
+ tmp = val & ~mask;
+ tmp |= v;
+ cpu_loongarch_store_stable_timer_config(env, tmp);
+ break;
CASE_CSR_XCHGQ(TVAL)
CASE_CSR_XCHGQ(CNTC)
+ CASE_CSR_XCHGQ(TINTCLR)
CASE_CSR_XCHGQ(LLBCTL)
CASE_CSR_XCHGQ(IMPCTL1)
CASE_CSR_XCHGQ(IMPCTL2)
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 74f4a63d15..fd0365cffd 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,6 +18,7 @@ loongarch_softmmu_ss.add(files(
'machine.c',
'tlb_helper.c',
'csr_helper.c',
+ 'stabletimer.c',
))
loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
diff --git a/target/loongarch/stabletimer.c b/target/loongarch/stabletimer.c
new file mode 100644
index 0000000000..a3bf32a865
--- /dev/null
+++ b/target/loongarch/stabletimer.c
@@ -0,0 +1,71 @@
+/*
+ * QEMU LoongArch timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/loongarch/loongarch.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+
+#define TIMER_PERIOD 10 /* 10 ns period for 100 Mhz frequency */
+#define STABLETIMER_TICK_MASK 0xfffffffffffcUL
+#define STABLETIMER_ENABLE 0x1UL
+
+/* LoongArch timer */
+uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env)
+{
+ return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env)
+{
+ uint64_t now, expire;
+
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ expire = timer_expire_time_ns(env->timer);
+
+ return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env,
+ uint64_t value)
+{
+ uint64_t now, next;
+
+ env->CSR_TCFG = value;
+ if (value & STABLETIMER_ENABLE) {
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD;
+ timer_mod(env->timer, next);
+ }
+}
+
+static void loongarch_stable_timer_cb(void *opaque)
+{
+ CPULoongArchState *env;
+ uint64_t now, next;
+
+ env = opaque;
+ if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD;
+ timer_mod(env->timer, next);
+ } else {
+ env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+ }
+
+ qemu_irq_raise(env->irq[IRQ_TIMER]);
+}
+
+void cpu_loongarch_clock_init(LoongArchCPU *cpu)
+{
+ CPULoongArchState *env = &cpu->env;
+
+ env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ &loongarch_stable_timer_cb, env);
+}
--
2.27.0
- [PATCH 00/31] Add Loongarch softmmu support., Xiaojuan Yang, 2021/10/19
- [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions(), Xiaojuan Yang, 2021/10/19
- [PATCH 02/31] target/loongarch: Add CSR registers definition, Xiaojuan Yang, 2021/10/19
- [PATCH 08/31] target/loongarch: Add tlb instruction support, Xiaojuan Yang, 2021/10/19
- [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU., Xiaojuan Yang, 2021/10/19
- [PATCH 11/31] target/loongarch: Add stabletimer support,
Xiaojuan Yang <=
- [PATCH 03/31] target/loongarch: Set default csr values., Xiaojuan Yang, 2021/10/19
- [PATCH 09/31] target/loongarch: Add other core instructions support, Xiaojuan Yang, 2021/10/19
- [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle, Xiaojuan Yang, 2021/10/19
- [PATCH 12/31] target/loongarch: Add timer related instructions support., Xiaojuan Yang, 2021/10/19
- [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform, Xiaojuan Yang, 2021/10/19
- [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC), Xiaojuan Yang, 2021/10/19