[PATCH] RISC-V: Resurrect the MMIO timer implementation for M-mode systems

Anup Patel Anup.Patel at wdc.com
Fri Sep 18 23:32:12 EDT 2020



> -----Original Message-----
> From: Palmer Dabbelt <palmerdabbelt at google.com>
> Sent: 19 September 2020 08:24
> To: Anup Patel <Anup.Patel at wdc.com>
> Cc: linux-riscv at lists.infradead.org; hch at infradead.org; kernel-
> team at android.com; anup at brainfault.org
> Subject: RE: [PATCH] RISC-V: Resurrect the MMIO timer implementation for
> M-mode systems
> 
> On Mon, 14 Sep 2020 19:11:46 PDT (-0700), Anup Patel wrote:
> >
> >
> >> -----Original Message-----
> >> From: Palmer Dabbelt <palmerdabbelt at google.com>
> >> Sent: 14 September 2020 22:27
> >> To: linux-riscv at lists.infradead.org
> >> Cc: hch at infradead.org; Anup Patel <Anup.Patel at wdc.com>; Palmer
> >> Dabbelt <palmerdabbelt at google.com>; kernel-team at android.com
> >> Subject: [PATCH] RISC-V: Resurrect the MMIO timer implementation for
> >> M- mode systems
> >>
> >> The K210 doesn't implement rdtime in M-mode, and since that's where
> >> Linux runs in the NOMMU systems that means we can't use rdtime.  The
> >> K210 is the only system that anyone is currently running NOMMU or
> >> M-mode on, so here we're just inlining the timer read directly.
> >>
> >> Signed-off-by: Palmer Dabbelt <palmerdabbelt at google.com>
> >> ---
> >> I don't actually have a K210 so I haven't tested this.  If nobody
> >> else has the time to I'll put together a QEMU that doesn't support
> >> rdtime in M-mode, but I've yet to mess around with the !MMU stuff so
> that might take a little while.
> >> This certainly doesn't seem worse than what's there right now,
> >> though, as rdtime isn't valid in M-mode on the K210 (our only M-mode
> platform).
> >
> > I think you missed my comments in the previous email thread.
> >
> > I would request to make this patch bit more CLINT independent.
> >
> > Please see inline below.
> >
> >> ---
> >>  arch/riscv/include/asm/clint.h    | 26 ++++++++++++++++++++++++++
> >>  arch/riscv/include/asm/timex.h    | 27 +++++++++++++++++++++++++++
> >>  drivers/clocksource/timer-clint.c | 17 +++++++++++++++++
> >>  3 files changed, 70 insertions(+)
> >>  create mode 100644 arch/riscv/include/asm/clint.h
> >>
> >> diff --git a/arch/riscv/include/asm/clint.h
> >> b/arch/riscv/include/asm/clint.h new file mode 100644 index
> >> 000000000000..0789fd37b40a
> >> --- /dev/null
> >> +++ b/arch/riscv/include/asm/clint.h
> >> @@ -0,0 +1,26 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-only */
> >> +/*
> >> + * Copyright (C) 2020 Google, Inc
> >> + */
> >> +
> >> +#ifndef _ASM_RISCV_CLINT_H
> >> +#define _ASM_RISCV_CLINT_H
> >> +
> >> +#include <linux/types.h>
> >> +#include <asm/mmio.h>
> >> +
> >> +#ifdef CONFIG_RISCV_M_MODE
> >> +/*
> >> + * This lives in the CLINT driver, but is accessed directly by
> >> +timex.h to avoid
> >> + * any overhead when accessing the MMIO timer.
> >> + *
> >> + * The ISA defines mtime as a 64-bit memory-mapped register that
> >> +increments at
> >> + * a constant frequency, but it doesn't define some other
> >> +constraints we depend
> >> + * on (most notably ordering constraints, but also some simpler
> >> +stuff like the
> >> + * memory layout).  Thus, this is called "clint_time_val" instead of
> >> +something
> >> + * like "riscv_mtime", to signify that these non-ISA assumptions must
> hold.
> >> + */
> >> +extern u64 __iomem *clint_time_val;
> >> +#endif
> >> +
> >> +#endif
> >> diff --git a/arch/riscv/include/asm/timex.h
> >> b/arch/riscv/include/asm/timex.h index a3fb85d505d4..7f659dda0032
> >> 100644
> >> --- a/arch/riscv/include/asm/timex.h
> >> +++ b/arch/riscv/include/asm/timex.h
> >> @@ -10,6 +10,31 @@
> >>
> >>  typedef unsigned long cycles_t;
> >
> > The entire asm/clint.h can be avoided by adding "extern u64 __iomem
> > *riscv_mmio_time_val;"
> > here in n asm/timex.h
> >
> > Also, this will make it bit more CLINT independent.
> 
> Except that, as per the comments, it's not CLINT independent.

We just need some 64bit MMIO register. It could be CLINT TIME register
or some other timer. I don't see anything CLINT specific apart from the
variable name "clint_time_val".

Regards,
Anup

> 
> >> +#ifdef CONFIG_RISCV_M_MODE
> >> +
> >> +#include <asm/clint.h>
> >> +
> >> +#ifdef CONFIG_64BIT
> >> +static inline cycles_t get_cycles(void) {
> >> +	return readq_relaxed(clint_time_val); } #else /* !CONFIG_64BIT */
> >> +static inline u32 get_cycles(void) {
> >> +	return readl_relaxed(((u32 *)clint_time_val)); } #define get_cycles
> >> +get_cycles
> >> +
> >> +static inline u32 get_cycles_hi(void) {
> >> +	return readl_relaxed(((u32 *)clint_time_val) + 1); } #define
> >> +get_cycles_hi get_cycles_hi #endif /* CONFIG_64BIT */
> >
> > Use riscv_mmio_time_val instead of clint_time_val above.
> >
> >> +
> >> +#else /* CONFIG_RISCV_M_MODE */
> >> +
> >>  static inline cycles_t get_cycles(void)  {
> >>  	return csr_read(CSR_TIME);
> >> @@ -41,6 +66,8 @@ static inline u64 get_cycles64(void)  }  #endif /*
> >> CONFIG_64BIT */
> >>
> >> +#endif /* !CONFIG_RISCV_M_MODE */
> >> +
> >>  #define ARCH_HAS_READ_CURRENT_TIMER
> >>  static inline int read_current_timer(unsigned long *timer_val)  {
> >> diff --git a/drivers/clocksource/timer-clint.c
> >> b/drivers/clocksource/timer-clint.c
> >> index 8eeafa82c03d..d17367dee02c 100644
> >> --- a/drivers/clocksource/timer-clint.c
> >> +++ b/drivers/clocksource/timer-clint.c
> >> @@ -19,6 +19,11 @@
> >>  #include <linux/interrupt.h>
> >>  #include <linux/of_irq.h>
> >>  #include <linux/smp.h>
> >> +#include <linux/timex.h>
> >> +
> >> +#ifndef CONFIG_RISCV_M_MODE
> >> +#include <asm/clint.h>
> >> +#endif
> >
> > As-per, above suggestion drop this #include.
> >
> >>
> >>  #define CLINT_IPI_OFF		0
> >>  #define CLINT_TIMER_CMP_OFF	0x4000
> >> @@ -31,6 +36,10 @@ static u64 __iomem *clint_timer_val;  static
> >> unsigned long clint_timer_freq;  static unsigned int clint_timer_irq;
> >>
> >> +#ifdef CONFIG_RISCV_M_MODE
> >> +u64 __iomem *clint_time_val;
> >> +#endif
> >
> > Define and export "u64 __iomem *riscv_mmio_time_val" in
> > arch/riscv/kernel/time.c
> >
> > This way no "clint_time_val" definition required here as well and
> > other MMIO timers can also set riscv_mmio_time_val.
> >
> >> +
> >>  static void clint_send_ipi(const struct cpumask *target)  {
> >>  	unsigned int cpu;
> >> @@ -184,6 +193,14 @@ static int __init clint_timer_init_dt(struct
> >> device_node *np)
> >>  	clint_timer_val = base + CLINT_TIMER_VAL_OFF;
> >>  	clint_timer_freq = riscv_timebase;
> >>
> >> +#ifdef CONFIG_RISCV_M_MODE
> >> +	/*
> >> +	 * Yes, that's an odd naming scheme.  time_val is public, but
> >> hopefully
> >> +	 * will die in favor of something cleaner.
> >> +	 */
> >> +	clint_time_val = clint_timer_val;
> >> +#endif
> >> +
> >
> > Just set " riscv_mmio_time_val = clint_timer_val" here.
> >
> >>  	pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);
> >>
> >>  	rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
> >> --
> >> 2.28.0.618.gf4bc123cb7-goog
> >
> > Regards,
> > Anup


More information about the linux-riscv mailing list