qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH v3 05/27] target/loongarch: Add stabletimer support


From: chen huacai
Subject: Re: [RFC PATCH v3 05/27] target/loongarch: Add stabletimer support
Date: Mon, 6 Dec 2021 12:38:35 +0800

Hi, Xiaojuan,

Maybe it is better to use "constant timer" instead of "stable timer",
which is more "native" in English.

Huacai

On Sat, Dec 4, 2021 at 8:11 PM Xiaojuan Yang <yangxiaojuan@loongson.cn> wrote:
>
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>  target/loongarch/cpu.c         |  9 +++++
>  target/loongarch/cpu.h         | 10 ++++++
>  target/loongarch/meson.build   |  1 +
>  target/loongarch/stabletimer.c | 63 ++++++++++++++++++++++++++++++++++
>  4 files changed, 83 insertions(+)
>  create mode 100644 target/loongarch/stabletimer.c
>
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 343632c644..f34e9763af 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -234,12 +234,21 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
> Error **errp)
>      LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
>      Error *local_err = NULL;
>
> +#ifndef CONFIG_USER_ONLY
> +    LoongArchCPU *cpu = LOONGARCH_CPU(dev);
> +#endif
> +
>      cpu_exec_realizefn(cs, &local_err);
>      if (local_err != NULL) {
>          error_propagate(errp, local_err);
>          return;
>      }
>
> +#ifndef CONFIG_USER_ONLY
> +    timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
> +                  &loongarch_stable_timer_cb, cpu);
> +#endif
> +
>      cpu_reset(cs);
>      qemu_init_vcpu(cs);
>
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index a4acd3b285..aeb8a5d397 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -12,6 +12,7 @@
>  #include "fpu/softfloat-types.h"
>  #include "hw/registerfields.h"
>  #include "cpu-csr.h"
> +#include "qemu/timer.h"
>
>  #define TCG_GUEST_DEFAULT_MO (0)
>
> @@ -148,6 +149,9 @@ FIELD(CPUCFG20, L3IU_SIZE, 24, 7)
>  extern const char * const regnames[];
>  extern const char * const fregnames[];
>
> +#define N_IRQS      14
> +#define IRQ_TIMER   11
> +
>  typedef struct CPULoongArchState CPULoongArchState;
>  struct CPULoongArchState {
>      uint64_t gpr[32];
> @@ -242,6 +246,7 @@ struct LoongArchCPU {
>
>      CPUNegativeOffsetState neg;
>      CPULoongArchState env;
> +    QEMUTimer timer; /* Internal timer */
>  };
>
>  #define TYPE_LOONGARCH_CPU "loongarch-cpu"
> @@ -306,4 +311,9 @@ enum {
>  #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
>  #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
>
> +void loongarch_stable_timer_cb(void *opaque);
> +uint64_t cpu_loongarch_get_stable_counter(LoongArchCPU *cpu);
> +uint64_t cpu_loongarch_get_stable_timer_ticks(LoongArchCPU *cpu);
> +void cpu_loongarch_store_stable_timer_config(LoongArchCPU *cpu,
> +                                             uint64_t value);
>  #endif /* LOONGARCH_CPU_H */
> diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
> index 103f36ee15..bda9f47ae4 100644
> --- a/target/loongarch/meson.build
> +++ b/target/loongarch/meson.build
> @@ -17,6 +17,7 @@ loongarch_tcg_ss.add(zlib)
>  loongarch_softmmu_ss = ss.source_set()
>  loongarch_softmmu_ss.add(files(
>    'machine.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..151f5073f5
> --- /dev/null
> +++ b/target/loongarch/stabletimer.c
> @@ -0,0 +1,63 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * QEMU LoongArch timer support
> + *
> + * Copyright (c) 2021 Loongson Technology Corporation Limited
> + */
> +
> +#include "qemu/osdep.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(LoongArchCPU *cpu)
> +{
> +    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
> +}
> +
> +uint64_t cpu_loongarch_get_stable_timer_ticks(LoongArchCPU *cpu)
> +{
> +    uint64_t now, expire;
> +
> +    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +    expire = timer_expire_time_ns(&cpu->timer);
> +
> +    return (expire - now) / TIMER_PERIOD;
> +}
> +
> +void cpu_loongarch_store_stable_timer_config(LoongArchCPU *cpu,
> +                                             uint64_t value)
> +{
> +    CPULoongArchState *env = &cpu->env;
> +    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(&cpu->timer, next);
> +    }
> +}
> +
> +void loongarch_stable_timer_cb(void *opaque)
> +{
> +    LoongArchCPU *cpu  = opaque;
> +    CPULoongArchState *env = &cpu->env;
> +    uint64_t now, next;
> +
> +    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(&cpu->timer, next);
> +    } else {
> +        env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
> +    }
> +
> +    env->CSR_ESTAT |= 1 << IRQ_TIMER;
> +    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
> +}
> --
> 2.27.0
>
>


-- 
Huacai Chen



reply via email to

[Prev in Thread] Current Thread [Next in Thread]