Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/alpha Improve time keeping and host CPU usage when ...
details: https://anonhg.NetBSD.org/src/rev/d750baf0965c
branches: trunk
changeset: 1014693:d750baf0965c
user: thorpej <thorpej%NetBSD.org@localhost>
date: Tue Sep 29 01:33:00 2020 +0000
description:
Improve time keeping and host CPU usage when running in Qemu:
- clockattach(): Allow multiple calls when running in Qemu. Anything
after this first one is ignored, but this gives us a change to use
a clock source provided by the VM directly, rather than relying on
a more expensive hardware emulation.
- Add cpu_initclocks_secondary(), to handle clock setup on secondary
CPUs, if needed.
- Allow us to use the WTINT PALcode call in cpu_idle() to idle in a lower
power state (Qemu's PALcode supports this).
- Use the Qemu per-cpu set-alarm-rel call as the hardclock interrupt
source. In Qemu environments, reduce hz to 50 (rather than the
default 1024) to give the clock a snowball's chance when running on
a host system with hz=100. XXX We have to manually re-calculate
tick and tickadj. There should be MI code to do this for us. Also
in Qemu environments, let hardclock() drive the sched clock by setting
schedhz=0.
diffstat:
sys/arch/alpha/alpha/clock.c | 24 ++++++++++--
sys/arch/alpha/alpha/cpu.c | 27 +++++++++++++-
sys/arch/alpha/alpha/qemu.c | 81 ++++++++++++++++++++++++++++++++++++++++++-
sys/arch/alpha/include/cpu.h | 8 +++-
4 files changed, 130 insertions(+), 10 deletions(-)
diffs (253 lines):
diff -r 13731dbd36ab -r d750baf0965c sys/arch/alpha/alpha/clock.c
--- a/sys/arch/alpha/alpha/clock.c Tue Sep 29 01:20:59 2020 +0000
+++ b/sys/arch/alpha/alpha/clock.c Tue Sep 29 01:33:00 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: clock.c,v 1.44 2020/09/27 23:17:36 thorpej Exp $ */
+/* $NetBSD: clock.c,v 1.45 2020/09/29 01:33:00 thorpej Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.44 2020/09/27 23:17:36 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.45 2020/09/29 01:33:00 thorpej Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -64,10 +64,16 @@
{
/*
- * Just bookkeeping.
+ * Just bookkeeping. We only allow one system clock. If
+ * we're running on real hardware, enforce this. If we're
+ * running under Qemu, anything after the first one.
*/
- if (clock_init != NULL)
+ if (clock_init != NULL) {
+ if (alpha_is_qemu) {
+ return;
+ }
panic("clockattach: multiple clocks");
+ }
clock_init = fns;
clockdev = dev;
}
@@ -114,6 +120,16 @@
}
/*
+ * Some platforms might have other per-cpu clock initialization. This
+ * is handled here.
+ */
+void
+cpu_initclocks_secondary(void)
+{
+ (*clock_init)(clockdev);
+}
+
+/*
* We assume newhz is either stathz or profhz, and that neither will
* change after being set up above. Could recalculate intervals here
* but that would be a drag.
diff -r 13731dbd36ab -r d750baf0965c sys/arch/alpha/alpha/cpu.c
--- a/sys/arch/alpha/alpha/cpu.c Tue Sep 29 01:20:59 2020 +0000
+++ b/sys/arch/alpha/alpha/cpu.c Tue Sep 29 01:33:00 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.100 2020/09/04 01:56:29 thorpej Exp $ */
+/* $NetBSD: cpu.c,v 1.101 2020/09/29 01:33:00 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -59,7 +59,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.100 2020/09/04 01:56:29 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.101 2020/09/29 01:33:00 thorpej Exp $");
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
@@ -100,6 +100,27 @@
void cpu_boot_secondary(struct cpu_info *);
#endif /* MULTIPROCESSOR */
+static void
+cpu_idle_default(void)
+{
+ /*
+ * Default is to do nothing. Platform code can overwrite
+ * as needed.
+ */
+}
+
+void
+cpu_idle_wtint(void)
+{
+ /*
+ * Some PALcode versions implement the WTINT call to idle
+ * in a low power mode.
+ */
+ alpha_pal_wtint(0);
+}
+
+void (*cpu_idle_fn)(void) __read_mostly = cpu_idle_default;
+
/*
* The Implementation Version and the Architecture Mask must be
* consistent across all CPUs in the system, so we set it for the
@@ -582,6 +603,8 @@
alpha_pal_imb();
cc_calibrate_cpu(ci);
+
+ cpu_initclocks_secondary();
}
int
diff -r 13731dbd36ab -r d750baf0965c sys/arch/alpha/alpha/qemu.c
--- a/sys/arch/alpha/alpha/qemu.c Tue Sep 29 01:20:59 2020 +0000
+++ b/sys/arch/alpha/alpha/qemu.c Tue Sep 29 01:33:00 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: qemu.c,v 1.1 2020/09/27 23:59:37 thorpej Exp $ */
+/* $NetBSD: qemu.c,v 1.2 2020/09/29 01:33:00 thorpej Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -38,12 +38,16 @@
#include <sys/device.h>
#include <sys/time.h>
#include <sys/timetc.h>
+#include <sys/kernel.h>
#include <sys/cpu.h>
#include <machine/autoconf.h>
+#include <machine/cpuconf.h>
#include <machine/rpb.h>
#include <machine/alpha.h>
+#include <alpha/alpha/clockvar.h>
+
extern struct cfdriver qemu_cd;
struct qemu_softc {
@@ -57,7 +61,7 @@
{
register unsigned long v0 __asm("$0");
register unsigned long a0 __asm("$16") = 7; /* Qemu get-time */
-
+
__asm volatile ("call_pal %2"
: "=r"(v0), "+r"(a0)
: "i"(PAL_cserve)
@@ -66,6 +70,69 @@
return (u_int)v0;
}
+static inline void
+qemu_set_alarm_relative(unsigned long nsec)
+{
+ register unsigned long a0 __asm("$16") = 5; /* Qemu set-alarm-rel */
+ register unsigned long a1 __asm("$17") = nsec;
+
+ __asm volatile ("call_pal %2"
+ : "+r"(a0), "+r"(a1)
+ : "i"(PAL_cserve)
+ : "$0", "$18", "$19", "$20", "$21");
+}
+
+static unsigned long qemu_nsec_per_tick __read_mostly;
+
+static void
+qemu_hardclock(struct clockframe * const framep)
+{
+ if (__predict_false(qemu_nsec_per_tick == 0)) {
+ /* Spurious; qemu_clock_init() hasn't been called yet. */
+ return;
+ }
+
+ /* Schedule the next tick before we process the current one. */
+ qemu_set_alarm_relative(qemu_nsec_per_tick);
+
+ hardclock(framep);
+}
+
+static void
+qemu_clock_init(void * const v __unused)
+{
+ /* First-time initialization... */
+ if (qemu_nsec_per_tick == 0) {
+ KASSERT(CPU_IS_PRIMARY(curcpu()));
+ qemu_nsec_per_tick = 1000000000UL / hz;
+
+ /*
+ * Override the clockintr routine; the Qemu alarm is
+ * one-shot, so we have to restart it for the next one.
+ */
+ platform.clockintr = qemu_hardclock;
+
+ /*
+ * hz=1024 is a little bananas for an emulated
+ * virtual machine. Reset to something more
+ * reasonable, and recalculate everything based
+ * on it.
+ */
+ hz = 50;
+ tick = 1000000 / hz;
+ tickadj = (240000 / (60 * hz)) ? (240000 / (60 * hz)) : 1;
+ schedhz = 0;
+
+ printf("Using the Qemu CPU alarm for %d Hz hardclock.\n", hz);
+ }
+
+ /*
+ * Note: We need to do this on each CPU, as the Qemu
+ * alarm is implemented as a per-CPU register.
+ */
+ qemu_set_alarm_relative(qemu_nsec_per_tick);
+}
+
static int
qemu_match(device_t parent, cfdata_t cfdata, void *aux)
{
@@ -98,6 +165,16 @@
tc->tc_frequency = 1000000000UL; /* nanosecond granularity */
tc->tc_priv = sc;
tc_init(tc);
+
+ /*
+ * Use the Qemu alarm as the system clock.
+ */
+ clockattach(qemu_clock_init, sc);
+
+ /*
+ * Qemu's PALcode implements WTINT; use it to save host cycles.
+ */
+ cpu_idle_fn = cpu_idle_wtint;
}
CFATTACH_DECL_NEW(qemu, sizeof(struct qemu_softc),
diff -r 13731dbd36ab -r d750baf0965c sys/arch/alpha/include/cpu.h
--- a/sys/arch/alpha/include/cpu.h Tue Sep 29 01:20:59 2020 +0000
+++ b/sys/arch/alpha/include/cpu.h Tue Sep 29 01:33:00 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.97 2020/09/25 03:40:11 thorpej Exp $ */
+/* $NetBSD: cpu.h,v 1.98 2020/09/29 01:33:00 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -242,7 +242,11 @@
void * cpu_uarea_alloc(bool);
bool cpu_uarea_free(void *);
-#define cpu_idle() /* nothing */
+void cpu_idle_wtint(void);
+extern void (*cpu_idle_fn)(void);
+#define cpu_idle() (*cpu_idle_fn)()
+
+void cpu_initclocks_secondary(void);
#endif /* _KERNEL */
#endif /* _ALPHA_CPU_H_ */
Home |
Main Index |
Thread Index |
Old Index