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),