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 */ _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"