svn commit: r297802 - head/sys/dev/hyperv/vmbus

Sepherosa Ziehau sephe at FreeBSD.org
Mon Apr 11 03:28:19 UTC 2016


Author: sephe
Date: Mon Apr 11 03:28:17 2016
New Revision: 297802
URL: https://svnweb.freebsd.org/changeset/base/297802

Log:
  hyperv: Identify Hyper-V features and recommends properly
  
  Features bits will be used to detect devices, e.g. timers, which
  do not have corresponding event channels.
  
  Submitted by:	Jun Su <junsu microsoft com>
  Reviewed by:	sephe, Dexuan Cui <decui microsoft com>
  Rearranged by:	sephe
  MFC after:	1 week
  Sponsored by:	Microsoft OSTC

Modified:
  head/sys/dev/hyperv/vmbus/hv_hv.c
  head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h

Modified: head/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_hv.c	Mon Apr 11 03:14:28 2016	(r297801)
+++ head/sys/dev/hyperv/vmbus/hv_hv.c	Mon Apr 11 03:28:17 2016	(r297802)
@@ -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 @@ __FBSDID("$FreeBSD$");
 
 static u_int hv_get_timecount(struct timecounter *tc);
 
+u_int	hyperv_features;
+u_int	hyperv_recommends;
+
 /**
  * Globals
  */
@@ -393,3 +397,88 @@ void hv_vmbus_synic_cleanup(void *arg)
 	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;
+}
+SYSINIT(hyperv_initialize, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hyperv_init, NULL);

Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Mon Apr 11 03:14:28 2016	(r297801)
+++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h	Mon Apr 11 03:28:17 2016	(r297802)
@@ -471,10 +471,17 @@ typedef enum {
 	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
  */


More information about the svn-src-head mailing list