diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-08-31 15:52:11 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-08-31 15:52:11 +0000 |
commit | 4d9139667c6f31eb790d7dee4c81d177674d307c (patch) | |
tree | ae25ebed3c0234d41507996c93a01217b077ff05 /sys/dev | |
parent | a6ff55c8c8dd34b44962521dd489c0dcc983bced (diff) |
When running on Hyper-V, make use of its timecounter as delay func in case
we're still using the i8254 for that. On Hyper-V Gen 2 VMs there is no
i8254 we can trust, so we need some kind of fallback, especially if there
is no TSC either.
Discussed with the hackroom
ok kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pv/hyperv.c | 12 | ||||
-rw-r--r-- | sys/dev/pv/pvbus.c | 13 |
2 files changed, 24 insertions, 1 deletions
diff --git a/sys/dev/pv/hyperv.c b/sys/dev/pv/hyperv.c index de753ccbfc9..dcebd3ae681 100644 --- a/sys/dev/pv/hyperv.c +++ b/sys/dev/pv/hyperv.c @@ -349,6 +349,18 @@ hv_gettime(struct timecounter *tc) return (now); } +void +hv_delay(int usecs) +{ + uint64_t interval, start; + + /* 10 MHz fixed frequency */ + interval = (uint64_t)usecs * 10; + start = rdmsr(MSR_HV_TIME_REF_COUNT); + while (rdmsr(MSR_HV_TIME_REF_COUNT) - start < interval) + CPU_BUSY_CYCLE(); +} + int hv_init_hypercall(struct hv_softc *sc) { diff --git a/sys/dev/pv/pvbus.c b/sys/dev/pv/pvbus.c index 19098a28d2f..b7bbe91ee33 100644 --- a/sys/dev/pv/pvbus.c +++ b/sys/dev/pv/pvbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pvbus.c,v 1.22 2020/08/26 03:29:06 visa Exp $ */ +/* $OpenBSD: pvbus.c,v 1.23 2021/08/31 15:52:10 patrick Exp $ */ /* * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> @@ -40,6 +40,9 @@ #include <dev/pv/pvvar.h> #include <dev/pv/pvreg.h> +#include <dev/pv/hypervreg.h> + +#include "hyperv.h" int has_hv_cpuid = 0; @@ -297,6 +300,8 @@ pvbus_kvm(struct pvbus_hv *hv) hv->hv_features = regs[0]; } +extern void hv_delay(int usecs); + void pvbus_hyperv(struct pvbus_hv *hv) { @@ -312,6 +317,12 @@ pvbus_hyperv(struct pvbus_hv *hv) HYPERV_VERSION_EBX_MAJOR_S; hv->hv_minor = (regs[1] & HYPERV_VERSION_EBX_MINOR_M) >> HYPERV_VERSION_EBX_MINOR_S; + +#if NHYPERV > 0 + if (hv->hv_features & CPUID_HV_MSR_TIME_REFCNT && + delay_func == i8254_delay) + delay_func = hv_delay; +#endif } void |