summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2021-08-31 15:52:11 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2021-08-31 15:52:11 +0000
commit4d9139667c6f31eb790d7dee4c81d177674d307c (patch)
treeae25ebed3c0234d41507996c93a01217b077ff05 /sys/dev
parenta6ff55c8c8dd34b44962521dd489c0dcc983bced (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.c12
-rw-r--r--sys/dev/pv/pvbus.c13
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