The clock on RISC-V is architectural, so we really don't need the
authorkettenis <kettenis@openbsd.org>
Tue, 4 May 2021 16:38:06 +0000 (16:38 +0000)
committerkettenis <kettenis@openbsd.org>
Tue, 4 May 2021 16:38:06 +0000 (16:38 +0000)
whole abstraction layer to support multiple timers.  And we don't
really need a separate driver.  Replace timer(4) with code based on
the powerpc64 implementation of the randomized statclock code.

Fixes hangs seen on real hardware.

ok jsg@, drahn@

sys/arch/riscv64/conf/GENERIC
sys/arch/riscv64/conf/RAMDISK
sys/arch/riscv64/conf/files.riscv64
sys/arch/riscv64/dev/mainbus.c
sys/arch/riscv64/dev/timer.c [deleted file]
sys/arch/riscv64/dev/timer.h [deleted file]
sys/arch/riscv64/include/cpu.h
sys/arch/riscv64/riscv64/clock.c [new file with mode: 0644]
sys/arch/riscv64/riscv64/cpu.c
sys/arch/riscv64/riscv64/intr.c
sys/arch/riscv64/riscv64/machdep.c

index ee9f0fc..4014ac7 100644 (file)
@@ -29,7 +29,6 @@ mainbus0      at root
 
 # cpu0
 cpu0           at mainbus0
-timer0         at cpu0
 intc0          at cpu0
 
 # NS16550 compatible serial ports
index 7955b94..4c6eb61 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.5 2021/04/25 02:48:00 jsg Exp $
+# $OpenBSD: RAMDISK,v 1.6 2021/05/04 16:38:06 kettenis Exp $
 #
 # GENERIC machine description file
 #
@@ -48,7 +48,6 @@ mainbus0      at root
 
 # cpu0
 cpu0           at mainbus0
-timer0         at cpu0
 intc0          at cpu0
 
 # NS16550 compatible serial ports
index 6111eec..2294c06 100644 (file)
@@ -12,6 +12,7 @@ file  arch/riscv64/riscv64/autoconf.c
 file   arch/riscv64/riscv64/ast.c
 file   arch/riscv64/riscv64/bus_space.c
 file   arch/riscv64/riscv64/bus_dma.c
+file   arch/riscv64/riscv64/clock.c
 file   arch/riscv64/riscv64/conf.c
 file   arch/riscv64/riscv64/disksubr.c         disk
 file   arch/riscv64/riscv64/locore.S
@@ -60,13 +61,6 @@ device       cpu
 attach cpu at mainbus
 file   arch/riscv64/riscv64/cpu.c              cpu
 
-#
-# timer
-#
-device timer
-attach timer at cpu
-file   arch/riscv64/dev/timer.c                timer
-
 #
 # HART-specific interrupt controller
 #
index a43d437..a6e0c32 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.4 2021/05/04 12:46:28 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.5 2021/05/04 16:38:06 kettenis Exp $ */
 /*
  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -91,8 +91,6 @@ mainbus_match(struct device *parent, void *cfdata, void *aux)
        return (1);
 }
 
-void riscv_timer_init(void);
-
 void
 mainbus_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -101,7 +99,6 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        int node, len;
 
        riscv_intr_init_fdt();
-       riscv_timer_init();
 
        sc->sc_node = OF_peer(0);
        sc->sc_iot = &riscv64_bs_tag;
diff --git a/sys/arch/riscv64/dev/timer.c b/sys/arch/riscv64/dev/timer.c
deleted file mode 100644 (file)
index 849b0c9..0000000
+++ /dev/null
@@ -1,368 +0,0 @@
-/*-
- * Copyright (c) 2015-2017 Ruslan Bukin <br@bsdpad.com>
- * All rights reserved.
- *
- * Portions of this software were developed by SRI International and the
- * University of Cambridge Computer Laboratory under DARPA/AFRL contract
- * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
- *
- * Portions of this software were developed by the University of Cambridge
- * Computer Laboratory as part of the CTSRD Project, with support from the
- * UK Higher Education Innovation Fund (HEIF).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * RISC-V Timer
- */
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/queue.h>
-#include <sys/malloc.h>
-#include <sys/device.h>
-#include <sys/kernel.h>
-#include <sys/timetc.h>
-
-#include <machine/intr.h>
-#include <machine/bus.h>
-#include <machine/cpufunc.h>
-#include <machine/fdt.h>
-#include <machine/sbi.h>
-
-#include "riscv_cpu_intc.h"
-
-#include <dev/ofw/fdt.h>
-#include <dev/ofw/openfirm.h>
-
-
-#define        TIMER_COUNTS            0x00
-#define        TIMER_MTIMECMP(cpu)     (cpu * 8)
-#define TIMER_FREQUENCY                10 * 1000 * 1000 /* RISC-V time clock */
-
-unsigned       riscv_timer_get_timecount(struct timecounter *);
-
-static struct timecounter riscv_timer_timecount = {
-       .tc_name           = "RISC-V Timecounter",
-       .tc_get_timecount  = riscv_timer_get_timecount,
-       .tc_poll_pps       = NULL,
-       .tc_counter_mask   = ~0u,
-       .tc_frequency      = 0,
-       .tc_quality        = 1000,
-       .tc_priv           = NULL,
-};
-
-struct riscv_timer_pcpu_softc {
-       uint64_t                pc_nexttickevent;
-       uint64_t                pc_nextstatevent;
-       u_int32_t               pc_ticks_err_sum;
-};
-
-struct riscv_timer_softc {
-       struct device            sc_dev;
-       int                      sc_node;
-
-       struct riscv_timer_pcpu_softc sc_pstat[MAXCPUS];
-
-       u_int32_t               sc_ticks_err_cnt;
-       u_int32_t               sc_ticks_per_second; // sc_clkfreq
-       u_int32_t               sc_ticks_per_intr;
-       u_int32_t               sc_statvar;
-       u_int32_t               sc_statmin;
-
-       void                    *sc_ih;
-};
-
-static struct riscv_timer_softc *riscv_timer_sc = NULL;
-
-int            riscv_timer_get_freq();
-int            riscv_timer_match(struct device *, void *, void *);
-void           riscv_timer_attach(struct device *, struct device *, void *);
-int            riscv_timer_intr(void *);
-void           riscv_timer_cpu_initclocks();
-void           riscv_timer_delay(u_int);
-void           riscv_timer_setstatclockrate(int);
-void           riscv_timer_startclock();
-
-struct cfattach timer_ca = {
-       sizeof (struct riscv_timer_softc), riscv_timer_match,
-       riscv_timer_attach
-};
-
-struct cfdriver timer_cd = {
-       NULL, "timer", DV_DULL
-};
-
-static inline uint64_t
-get_cycles()
-{
-       return (rdtime());
-}
-
-long
-get_counts(struct riscv_timer_softc *sc)
-{
-       uint64_t counts;
-
-       counts = get_cycles();
-
-       return (counts);
-}
-
-unsigned
-riscv_timer_get_timecount(struct timecounter *tc)
-{
-       struct riscv_timer_softc *sc;
-
-       sc = tc->tc_priv;
-
-       return (get_counts(sc));
-}
-
-int
-riscv_timer_get_freq()
-{
-       int node, len;
-
-       node = OF_finddevice("/cpus");
-       if (node == -1) {
-               printf("Can't find cpus node.\n");
-               return (0);
-       }
-
-       len = OF_getproplen(node, "timebase-frequency");
-       if (len != 4) {
-               printf("Can't find timebase-frequency property.\n");
-               return (0);
-       }
-
-       return OF_getpropint(node, "timebase-frequency", 0);
-}
-
-int
-riscv_timer_match(struct device *parent, void *cfdata, void *aux)
-{
-       if (riscv_timer_sc)     //already attached
-               return 0;
-
-       int node;
-       // struct fdt_attach_args *fa = (struct fdt_attach_args *)aux;
-
-       /*
-        * return 1 if:
-        * we can find valid "timebase-frequency" property from cpus
-        */
-       if ( (node = OF_finddevice("/cpus")) == 0)
-               return 0;
-
-       return (OF_getproplen(node, "timebase-frequency") == 4);//32bit uint
-}
-
-void
-riscv_timer_attach(struct device *parent, struct device *self, void *aux)
-{
-       struct riscv_timer_softc *sc = (struct riscv_timer_softc *)self;
-
-       if (riscv_timer_sc)/* already attached */
-               return;
-
-       sc->sc_ticks_per_second = riscv_timer_get_freq();
-       if (sc->sc_ticks_per_second == 0) {
-               printf("Failed to resolve RISC-V Timer timebase\n");
-               return;
-       }
-       printf(": tick rate %d KHz\n", sc->sc_ticks_per_second/1000);
-
-       riscv_timer_sc = sc;
-       stathz = 0;
-
-       riscv_clock_register(riscv_timer_cpu_initclocks, riscv_timer_delay,
-           riscv_timer_setstatclockrate, riscv_timer_startclock);
-
-       riscv_timer_timecount.tc_frequency = sc->sc_ticks_per_second;
-       riscv_timer_timecount.tc_priv = sc;
-
-       tc_init(&riscv_timer_timecount);
-}
-
-
-int timer_mindelta = 0; /* what should this be? */
-int
-riscv_timer_intr(void *frame)
-{
-       struct riscv_timer_softc *sc;
-       uint64_t next, now, newnow;
-       int timermissed = 0;
-       u_int new_hz = 100;
-       int s;
-
-#ifdef DEBUG_TIMER
-       printf("RISC-V Timer Interrupt\n");
-#endif
-
-       sc = riscv_timer_sc;
-
-       s = splclock();
-
-       if (s < IPL_CLOCK)
-               hardclock(frame);
-
-       // XXX should base timer interval from the expected
-       // time of expiration, not 'now'
-       now = get_cycles();
-       next = now + ((sc->sc_ticks_per_second / new_hz));
-
-       do {
-               newnow = get_cycles();
-               if (next < (newnow + timer_mindelta)) {
-                       /* slowly scale up miss timer. */
-                       if (timermissed > 1)
-                               timer_mindelta ++;
-               }
-               next = newnow + timer_mindelta;
-               sbi_set_timer(next);
-               csr_set(sip, SIE_STIE);
-
-               /* re-read current time to verif
-                * time hasn't been set into the past
-                */
-
-               newnow = get_cycles();
-               /* if we missed more than once, increment the min period */
-               timermissed++;
-       } while (next <= newnow);
-
-       splx(s);
-       return (1); // Handled
-}
-
-void
-riscv_timer_cpu_initclocks()
-{
-       struct riscv_timer_softc        *sc = timer_cd.cd_devs[0];
-       struct riscv_timer_pcpu_softc   *pc =
-               &sc->sc_pstat[CPU_INFO_UNIT(curcpu())];
-       uint64_t                         next;
-
-       stathz = hz;
-       profhz = hz * 10;
-
-       riscv_timer_setstatclockrate(stathz);
-
-       sc->sc_ticks_per_intr = sc->sc_ticks_per_second / hz;
-       sc->sc_ticks_err_cnt = sc->sc_ticks_per_second % hz;
-       pc->pc_ticks_err_sum = 0;
-
-       /* configure virtual timer interrupt */
-       sc->sc_ih = riscv_intc_intr_establish(IRQ_TIMER_SUPERVISOR, 0,
-                       riscv_timer_intr, NULL, "timer");
-
-       next = get_cycles() + sc->sc_ticks_per_intr;
-       pc->pc_nexttickevent = pc->pc_nextstatevent = next;
-
-       sbi_set_timer(next);
-       csr_set(sie, SIE_STIE);
-}
-
-void
-riscv_timer_delay(u_int usec)
-{
-       int64_t counts, counts_per_usec;
-       uint64_t first, last;
-
-       /*
-        * Check the timers are setup, if not just
-        * use a for loop for the meantime
-        */
-       if (riscv_timer_sc == NULL) {
-               for (; usec > 0; usec--)
-                       for (counts = 200; counts > 0; counts--)
-                               /*
-                                * Prevent the compiler from optimizing
-                                * out the loop
-                                */
-                               cpufunc_nullop();
-               return;
-       }
-
-       /* Get the number of times to count */
-       counts_per_usec = ((riscv_timer_timecount.tc_frequency / 1000000) + 1);
-
-       /*
-        * Clamp the timeout at a maximum value (about 32 seconds with
-        * a 66MHz clock). *Nobody* should be delay()ing for anywhere
-        * near that length of time and if they are, they should be hung
-        * out to dry.
-        */
-       if (usec >= (0x80000000U / counts_per_usec))
-               counts = (0x80000000U / counts_per_usec) - 1;
-       else
-               counts = usec * counts_per_usec;
-
-       first = get_counts(riscv_timer_sc);
-
-       while (counts > 0) {
-               last = get_counts(riscv_timer_sc);
-               counts -= (int64_t)(last - first);
-               first = last;
-       }
-}
-
-void
-riscv_timer_setstatclockrate(int newhz)
-{
-       /* dummy: clockrate on riscv is fixed*/
-}
-
-/* is only called from secondary cpu */
-void
-riscv_timer_startclock()
-{
-       struct riscv_timer_softc        *sc = timer_cd.cd_devs[0];
-       struct riscv_timer_pcpu_softc   *pc =
-               &sc->sc_pstat[CPU_INFO_UNIT(curcpu())];
-       uint64_t nextevent;
-
-       nextevent = get_cycles() + sc->sc_ticks_per_intr;
-       pc->pc_nexttickevent = pc->pc_nextstatevent = nextevent;
-
-       riscv_intr_route(sc->sc_ih, 1, curcpu());
-
-       sbi_set_timer(nextevent);
-       csr_set(sie, SIE_STIE);
-}
-
-/*
- * called at early mainbus_attach, to provide delay func
- * before timer and interrupt is ready
- */
-void
-riscv_timer_init(void)
-{
-       uint64_t cntfrq = 0;
-
-       cntfrq = riscv_timer_get_freq();
-
-       if (cntfrq != 0) {
-               riscv_clock_register(NULL, riscv_timer_delay, NULL, NULL);
-       }
-}
diff --git a/sys/arch/riscv64/dev/timer.h b/sys/arch/riscv64/dev/timer.h
deleted file mode 100644 (file)
index bab1a36..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2020 Mars Li <mengshi.li.mars@gmail.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#ifndef        _MACHINE_TIMER_H_
-#define        _MACHINE_TIMER_H_
-
-int    riscv_timer_match(struct device *, void *, void *);
-
-#endif /* _MACHINE_TIMER_H_ */
index cdcfe69..db001ab 100644 (file)
@@ -95,6 +95,11 @@ struct cpu_info {
 
        u_int32_t               ci_ctrl; /* The CPU control register */
 
+       uint64_t                ci_lasttb;
+       uint64_t                ci_nexttimerevent;
+       uint64_t                ci_nextstatevent;
+       int                     ci_statspending;
+
        uint32_t                ci_cpl;
        uint32_t                ci_ipending;
        uint32_t                ci_idepth;
diff --git a/sys/arch/riscv64/riscv64/clock.c b/sys/arch/riscv64/riscv64/clock.c
new file mode 100644 (file)
index 0000000..9ee3bb7
--- /dev/null
@@ -0,0 +1,195 @@
+/*     $OpenBSD: clock.c,v 1.1 2021/05/04 16:38:06 kettenis Exp $      */
+
+/*
+ * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
+ * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/evcount.h>
+#include <sys/timetc.h>
+
+#include <machine/cpufunc.h>
+#include <machine/sbi.h>
+
+#include <riscv64/dev/riscv_cpu_intc.h>
+
+extern uint32_t tb_freq;       /* machdep.c */
+
+uint64_t tick_increment;
+uint64_t statmin;
+uint32_t statvar;
+
+struct evcount clock_count;
+struct evcount stat_count;
+
+u_int  tb_get_timecount(struct timecounter *);
+
+static struct timecounter tb_timecounter = {
+       .tc_get_timecount = tb_get_timecount,
+       .tc_poll_pps = NULL,
+       .tc_counter_mask = 0xffffffff,
+       .tc_frequency = 0,
+       .tc_name = "tb",
+       .tc_quality = 0,
+       .tc_priv = NULL,
+};
+
+void   cpu_startclock(void);
+int    clock_intr(void *);
+
+u_int
+tb_get_timecount(struct timecounter *tc)
+{
+       return rdtime();
+}
+
+void
+cpu_initclocks(void)
+{
+       tick_increment = tb_freq / hz;
+
+       stathz = 100;
+       profhz = 1000; /* must be a multiple of stathz */
+
+       setstatclockrate(stathz);
+
+       riscv_intc_intr_establish(IRQ_TIMER_SUPERVISOR, 0,
+           clock_intr, NULL, NULL);
+
+       evcount_attach(&clock_count, "clock", NULL);
+       evcount_attach(&stat_count, "stat", NULL);
+
+       cpu_startclock();
+
+       tb_timecounter.tc_frequency = tb_freq;
+       tc_init(&tb_timecounter);
+}
+
+void
+cpu_startclock(void)
+{
+       struct cpu_info *ci = curcpu();
+       uint64_t nextevent;
+
+       ci->ci_lasttb = rdtime();
+       ci->ci_nexttimerevent = ci->ci_lasttb + tick_increment;
+       nextevent = ci->ci_nextstatevent = ci->ci_nexttimerevent;
+
+       sbi_set_timer(nextevent);
+       csr_set(sie, SIE_STIE);
+}
+
+int
+clock_intr(void *frame)
+{
+       struct cpu_info *ci = curcpu();
+       uint64_t tb, prevtb;
+       uint64_t nextevent;
+       uint32_t r;
+       int nstats;
+       int s;
+
+       /*
+        * Based on the actual time delay since the last clock interrupt,
+        * we arrange for earlier interrupt next time.
+        */
+
+       tb = rdtime();
+
+       while (ci->ci_nexttimerevent <= tb)
+               ci->ci_nexttimerevent += tick_increment;
+
+       prevtb = ci->ci_nexttimerevent - tick_increment;
+
+       for (nstats = 0; ci->ci_nextstatevent <= tb; nstats++) {
+               do {
+                       r = random() & (statvar - 1);
+               } while (r == 0); /* random == 0 not allowed */
+               ci->ci_nextstatevent += statmin + r;
+       }
+       stat_count.ec_count += nstats;
+
+       if (ci->ci_nexttimerevent < ci->ci_nextstatevent)
+               nextevent = ci->ci_nexttimerevent;
+       else
+               nextevent = ci->ci_nextstatevent;
+
+       sbi_set_timer(nextevent);
+
+       if (ci->ci_cpl >= IPL_CLOCK) {
+               ci->ci_statspending += nstats;
+       } else {
+               nstats += ci->ci_statspending;
+               ci->ci_statspending = 0;
+
+               s = splclock();
+               intr_enable();
+
+               /*
+                * Do standard timer interrupt stuff.
+                */
+               while (ci->ci_lasttb < prevtb) {
+                       ci->ci_lasttb += tick_increment;
+                       clock_count.ec_count++;
+                       hardclock((struct clockframe *)frame);
+               }
+
+               while (nstats-- > 0)
+                       statclock((struct clockframe *)frame);
+
+               intr_disable();
+               splx(s);
+       }
+
+       return 0;
+}
+
+void
+setstatclockrate(int newhz)
+{
+       uint64_t stat_increment;
+       uint64_t min_increment;
+       uint32_t var;
+       u_long msr;
+
+       msr = intr_disable();
+
+       stat_increment = tb_freq / newhz;
+       var = 0x40000000; /* really big power of two */
+       /* Find largest 2^n which is nearly smaller than statint/2. */
+       min_increment = stat_increment / 2 + 100;
+       while (var > min_increment)
+               var >>= 1;
+
+       /* Not atomic, but we can probably live with that. */
+       statmin = stat_increment - (var >> 1);
+       statvar = var;
+
+       intr_restore(msr);
+}
+
+void
+delay(u_int us)
+{
+       uint64_t tb;
+
+       tb = rdtime();
+       tb += (us * tb_freq + 999999) / 1000000;
+       while (tb > rdtime())
+               continue;
+}
index 10516dd..89b49fe 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <machine/fdt.h>
 #include <machine/riscvreg.h>
-#include "../dev/timer.h"
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_clock.h>
@@ -158,15 +157,6 @@ cpu_attach(struct device *parent, struct device *dev, void *aux)
                        cpu_cpuspeed = cpu_clockspeed;
                }
 
-               /*
-                * attach cpu-embedded timer
-                * Trick: timer has no fdt node to match,
-                * riscv_timer_match will always return 1 at first call,
-                * and return 0 for all following calls,
-                * therefore, must attach timer before any node
-                */
-               config_found_sm(dev, NULL, NULL, riscv_timer_match);
-
                /*
                 * attach cpu's children node, so far there is only the
                 * cpu-embedded interrupt controller
index 639cbe6..7b605f8 100644 (file)
@@ -516,81 +516,6 @@ riscv_splassert_check(int wantipl, const char *func)
 }
 #endif
 
-/*
- ********* timer interrupt relevant **************
- */
-
-void riscv_dflt_delay(u_int usecs);
-
-struct {
-       void    (*delay)(u_int);
-       void    (*initclocks)(void);
-       void    (*setstatclockrate)(int);
-       void    (*mpstartclock)(void);
-} riscv_clock_func = {
-       riscv_dflt_delay,
-       NULL,
-       NULL,
-       NULL
-};
-
-void
-riscv_clock_register(void (*initclock)(void), void (*delay)(u_int),
-    void (*statclock)(int), void(*mpstartclock)(void))
-{
-       if (riscv_clock_func.initclocks)
-               return;
-
-       riscv_clock_func.initclocks = initclock;
-       riscv_clock_func.delay = delay;
-       riscv_clock_func.setstatclockrate = statclock;
-       riscv_clock_func.mpstartclock = mpstartclock;
-}
-
-void
-delay(u_int usec)
-{
-       riscv_clock_func.delay(usec);
-}
-
-void
-cpu_initclocks(void)
-{
-       if (riscv_clock_func.initclocks == NULL)
-               panic("initclocks function not initialized yet");
-
-       riscv_clock_func.initclocks();
-}
-
-void
-cpu_startclock(void)
-{
-       if (riscv_clock_func.mpstartclock == NULL)
-               panic("startclock function not initialized yet");
-
-       riscv_clock_func.mpstartclock();
-}
-
-void
-riscv_dflt_delay(u_int usecs)
-{
-       int j;
-       /* BAH - there is no good way to make this close */
-       /* but this isn't supposed to be used after the real clock attaches */
-       for (; usecs > 0; usecs--)
-               for (j = 100; j > 0; j--)
-                       ;
-}
-
-void
-setstatclockrate(int new)
-{
-       if (riscv_clock_func.setstatclockrate == NULL) {
-               panic("riscv_clock_func.setstatclockrate not initialized");
-       }
-       riscv_clock_func.setstatclockrate(new);
-}
-
 void
 intr_barrier(void *ih)
 {
index 7fae71c..8a971c3 100644 (file)
@@ -97,6 +97,8 @@ uint32_t boot_hart;   /* The hart we booted on. */
 struct cpu_info cpu_info_primary;
 struct cpu_info *cpu_info[MAXCPUS] = { &cpu_info_primary };
 
+uint32_t tb_freq = 1000000;
+
 struct fdt_reg memreg[VM_PHYSSEG_MAX];
 int nmemreg;
 
@@ -561,6 +563,16 @@ initriscv(struct riscv_bootparams *rbp)
        struct fdt_reg reg;
        void *node;
 
+       node = fdt_find_node("/cpus");
+       if (node != NULL) {
+               char *prop;
+               int len;
+
+               len = fdt_node_property(node, "timebase-frequency", &prop);
+               if (len == sizeof(tb_freq))
+                       tb_freq = bemtoh32((uint32_t *)prop);
+       }
+
        node = fdt_find_node("/chosen");
        if (node != NULL) {
                char *prop;