155 lines
3.8 KiB
Diff
155 lines
3.8 KiB
Diff
--- sys/dev/hyperv/vmbus/hv_hv.c.orig
|
|
+++ sys/dev/hyperv/vmbus/hv_hv.c
|
|
@@ -33,6 +33,7 @@
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/param.h>
|
|
+#include <sys/kernel.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/pcpu.h>
|
|
#include <sys/timetc.h>
|
|
@@ -50,6 +51,9 @@
|
|
|
|
static u_int hv_get_timecount(struct timecounter *tc);
|
|
|
|
+u_int hyperv_features;
|
|
+u_int hyperv_recommends;
|
|
+
|
|
/**
|
|
* Globals
|
|
*/
|
|
@@ -211,8 +215,6 @@
|
|
|
|
hv_vmbus_g_context.hypercall_page = virt_addr;
|
|
|
|
- tc_init(&hv_timecounter); /* register virtual timecount */
|
|
-
|
|
hv_et_init();
|
|
|
|
return (0);
|
|
@@ -427,3 +429,93 @@
|
|
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
|
|
}
|
|
|
|
+static bool
|
|
+hyperv_identify(void)
|
|
+{
|
|
+ u_int regs[4];
|
|
+ unsigned int maxLeaf;
|
|
+ unsigned int op;
|
|
+
|
|
+ if (vm_guest != VM_GUEST_HV)
|
|
+ return (false);
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
|
|
+ do_cpuid(op, regs);
|
|
+ maxLeaf = regs[0];
|
|
+ if (maxLeaf < HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS)
|
|
+ return (false);
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
|
|
+ do_cpuid(op, regs);
|
|
+ if (regs[0] != 0x31237648 /* HV#1 */)
|
|
+ return (false);
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_MS_HV_FEATURES;
|
|
+ do_cpuid(op, regs);
|
|
+ if ((regs[0] & HV_FEATURE_MSR_HYPERCALL) == 0) {
|
|
+ /*
|
|
+ * Hyper-V w/o Hypercall is impossible; someone
|
|
+ * is faking Hyper-V.
|
|
+ */
|
|
+ return (false);
|
|
+ }
|
|
+ hyperv_features = regs[0];
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
|
|
+ do_cpuid(op, regs);
|
|
+ printf("Hyper-V Version: %d.%d.%d [SP%d]\n",
|
|
+ regs[1] >> 16, regs[1] & 0xffff, regs[0], regs[2]);
|
|
+
|
|
+ printf(" Features: 0x%b\n", hyperv_features,
|
|
+ "\020"
|
|
+ "\001VPRUNTIME"
|
|
+ "\002TMREFCNT"
|
|
+ "\003SYNCIC"
|
|
+ "\004SYNCTM"
|
|
+ "\005APIC"
|
|
+ "\006HYERCALL"
|
|
+ "\007VPINDEX"
|
|
+ "\010RESET"
|
|
+ "\011STATS"
|
|
+ "\012REFTSC"
|
|
+ "\013IDLE"
|
|
+ "\014TMFREQ"
|
|
+ "\015DEBUG");
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION;
|
|
+ do_cpuid(op, regs);
|
|
+ hyperv_recommends = regs[0];
|
|
+ if (bootverbose)
|
|
+ printf(" Recommends: %08x %08x\n", regs[0], regs[1]);
|
|
+
|
|
+ op = HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS;
|
|
+ do_cpuid(op, regs);
|
|
+ if (bootverbose) {
|
|
+ printf(" Limits: Vcpu:%d Lcpu:%d Int:%d\n",
|
|
+ regs[0], regs[1], regs[2]);
|
|
+ }
|
|
+
|
|
+ if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE) {
|
|
+ op = HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE;
|
|
+ do_cpuid(op, regs);
|
|
+ if (bootverbose) {
|
|
+ printf(" HW Features: %08x AMD: %08x\n",
|
|
+ regs[0], regs[3]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return (true);
|
|
+}
|
|
+
|
|
+static void
|
|
+hyperv_init(void *dummy __unused)
|
|
+{
|
|
+ if (!hyperv_identify())
|
|
+ return;
|
|
+
|
|
+ if (hyperv_features & HV_FEATURE_MSR_TIME_REFCNT) {
|
|
+ /* Register virtual timecount */
|
|
+ tc_init(&hv_timecounter);
|
|
+ }
|
|
+}
|
|
+SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, NULL);
|
|
--- sys/dev/hyperv/vmbus/hv_vmbus_priv.h.orig
|
|
+++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h
|
|
@@ -471,10 +471,17 @@
|
|
HV_CPU_ID_FUNCTION_MS_HV_VERSION = 0x40000002,
|
|
HV_CPU_ID_FUNCTION_MS_HV_FEATURES = 0x40000003,
|
|
HV_CPU_ID_FUNCTION_MS_HV_ENLIGHTENMENT_INFORMATION = 0x40000004,
|
|
- HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005
|
|
-
|
|
+ HV_CPU_ID_FUNCTION_MS_HV_IMPLEMENTATION_LIMITS = 0x40000005,
|
|
+ HV_CPU_ID_FUNCTION_MS_HV_HARDWARE_FEATURE = 0x40000006
|
|
} hv_vmbus_cpuid_function;
|
|
|
|
+#define HV_FEATURE_MSR_TIME_REFCNT (1 << 1)
|
|
+#define HV_FEATURE_MSR_SYNCIC (1 << 2)
|
|
+#define HV_FEATURE_MSR_STIMER (1 << 3)
|
|
+#define HV_FEATURE_MSR_APIC (1 << 4)
|
|
+#define HV_FEATURE_MSR_HYPERCALL (1 << 5)
|
|
+#define HV_FEATURE_MSR_GUEST_IDLE (1 << 10)
|
|
+
|
|
/*
|
|
* Define the format of the SIMP register
|
|
*/
|
|
@@ -628,6 +635,9 @@
|
|
extern hv_vmbus_context hv_vmbus_g_context;
|
|
extern hv_vmbus_connection hv_vmbus_g_connection;
|
|
|
|
+extern u_int hyperv_features;
|
|
+extern u_int hyperv_recommends;
|
|
+
|
|
typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg);
|
|
|
|
typedef struct hv_vmbus_channel_msg_table_entry {
|