Module Name: src
Committed By: thorpej
Date: Sat Oct 3 17:32:49 UTC 2020
Modified Files:
src/sys/arch/alpha/alpha: qemu.c
Log Message:
Provide an alternate delay function that uses the Qemu get-time hypercall.
To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/alpha/alpha/qemu.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/alpha/alpha/qemu.c
diff -u src/sys/arch/alpha/alpha/qemu.c:1.2 src/sys/arch/alpha/alpha/qemu.c:1.3
--- src/sys/arch/alpha/alpha/qemu.c:1.2 Tue Sep 29 01:33:00 2020
+++ src/sys/arch/alpha/alpha/qemu.c Sat Oct 3 17:32:49 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: qemu.c,v 1.2 2020/09/29 01:33:00 thorpej Exp $ */
+/* $NetBSD: qemu.c,v 1.3 2020/10/03 17:32:49 thorpej Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -56,8 +56,10 @@ struct qemu_softc {
struct timecounter sc_tc;
};
-static u_int
-qemu_get_timecount(struct timecounter * const tc __unused)
+static unsigned long qemu_nsec_per_tick __read_mostly = (unsigned long)-1;
+
+static inline unsigned long
+qemu_get_vmtime(void)
{
register unsigned long v0 __asm("$0");
register unsigned long a0 __asm("$16") = 7; /* Qemu get-time */
@@ -67,7 +69,41 @@ qemu_get_timecount(struct timecounter *
: "i"(PAL_cserve)
: "$17", "$18", "$19", "$20", "$21");
- return (u_int)v0;
+ return v0;
+}
+
+static void
+qemu_delay(unsigned long usec)
+{
+ /* Get starting point. */
+ const unsigned long base = qemu_get_vmtime();
+
+ /* convert request from usec to nsec */
+ const unsigned long nsec = usec * 1000;
+ KASSERT(nsec > usec);
+
+ /* Figure out finish line. */
+ const unsigned long finished = base + nsec;
+ KASSERT(finished > base);
+
+ unsigned long now;
+
+ /* Spin until we're finished. */
+ while ((now = qemu_get_vmtime()) < finished) {
+ /*
+ * If we have more than one clock tick worth of spinning
+ * to do, when use WTINT to wait at a low power state.
+ */
+ if (finished - now > qemu_nsec_per_tick) {
+ alpha_pal_wtint(0);
+ }
+ }
+}
+
+static u_int
+qemu_get_timecount(struct timecounter * const tc __unused)
+{
+ return (u_int)qemu_get_vmtime();
}
static inline void
@@ -82,8 +118,6 @@ qemu_set_alarm_relative(unsigned long ns
: "$0", "$18", "$19", "$20", "$21");
}
-static unsigned long qemu_nsec_per_tick __read_mostly;
-
static void
qemu_hardclock(struct clockframe * const framep)
{
@@ -102,7 +136,7 @@ static void
qemu_clock_init(void * const v __unused)
{
/* First-time initialization... */
- if (qemu_nsec_per_tick == 0) {
+ if (qemu_nsec_per_tick == (unsigned long)-1) {
KASSERT(CPU_IS_PRIMARY(curcpu()));
qemu_nsec_per_tick = 1000000000UL / hz;
@@ -175,6 +209,11 @@ qemu_attach(device_t parent, device_t se
* Qemu's PALcode implements WTINT; use it to save host cycles.
*/
cpu_idle_fn = cpu_idle_wtint;
+
+ /*
+ * Use Qemu's "VM time" hypercall to implement delay().
+ */
+ alpha_delay_fn = qemu_delay;
}
CFATTACH_DECL_NEW(qemu, sizeof(struct qemu_softc),