Index: head/sys/dev/hyperv/vmbus/hv_et.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_et.c +++ head/sys/dev/hyperv/vmbus/hv_et.c @@ -39,6 +39,7 @@ #include #include +#include #define HV_TIMER_FREQUENCY (10 * 1000 * 1000LL) /* 100ns period */ #define HV_MAX_DELTA_TICKS 0xffffffffLL @@ -48,6 +49,16 @@ ((((uint64_t)HV_VMBUS_TIMER_SINT) << MSR_HV_STIMER_CFG_SINT_SHIFT) & \ MSR_HV_STIMER_CFG_SINT_MASK) +/* + * Two additionally required features: + * - SynIC is needed for interrupt generation. + * - Time reference counter is needed to set ABS reference count to + * STIMER0_COUNT. + */ +#define CPUID_HV_ET_MASK (CPUID_HV_MSR_TIME_REFCNT | \ + CPUID_HV_MSR_SYNIC | \ + CPUID_HV_MSR_SYNTIMER) + static struct eventtimer *et; static inline uint64_t @@ -104,7 +115,8 @@ static void hv_et_identify(driver_t *driver, device_t parent) { - if (device_find_child(parent, "hv_et", -1) != NULL) + if (device_find_child(parent, "hv_et", -1) != NULL || + (hyperv_features & CPUID_HV_ET_MASK) != CPUID_HV_ET_MASK) return; device_add_child(parent, "hv_et", -1); Index: head/sys/dev/hyperv/vmbus/hv_hv.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_hv.c +++ head/sys/dev/hyperv/vmbus/hv_hv.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #define HV_NANOSECONDS_PER_SEC 1000000000L Index: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c =================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -215,10 +216,21 @@ uint64_t val, orig; uint32_t sint; - /* - * Save virtual processor id. - */ - VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX); + if (hyperv_features & CPUID_HV_MSR_VP_INDEX) { + /* + * Save virtual processor id. + */ + VMBUS_PCPU_GET(sc, vcpuid, cpu) = rdmsr(MSR_HV_VP_INDEX); + } else { + /* + * XXX + * Virtual processoor id is only used by a pretty broken + * channel selection code from storvsc. It's nothing + * critical even if CPUID_HV_MSR_VP_INDEX is not set; keep + * moving on. + */ + VMBUS_PCPU_GET(sc, vcpuid, cpu) = cpu; + } /* * Setup the SynIC message. @@ -557,7 +569,8 @@ vmbus_probe(device_t dev) { if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL || - device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV) + device_get_unit(dev) != 0 || vm_guest != VM_GUEST_HV || + (hyperv_features & CPUID_HV_MSR_SYNIC) == 0) return (ENXIO); device_set_desc(dev, "Hyper-V Vmbus"); Index: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h =================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -451,9 +451,6 @@ 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 { Index: head/sys/dev/hyperv/vmbus/hyperv_reg.h =================================================================== --- head/sys/dev/hyperv/vmbus/hyperv_reg.h +++ head/sys/dev/hyperv/vmbus/hyperv_reg.h @@ -110,7 +110,8 @@ #define CPUID_HV_MSR_APIC 0x0010 /* MSR_HV_{EOI,ICR,TPR} */ #define CPUID_HV_MSR_HYPERCALL 0x0020 /* MSR_HV_GUEST_OS_ID * MSR_HV_HYPERCALL */ -#define CPUID_HV_MSR_GUEST_IDLE 0x0400 /* MSR_VH_GUEST_IDLE */ +#define CPUID_HV_MSR_VP_INDEX 0x0040 /* MSR_HV_VP_INDEX */ +#define CPUID_HV_MSR_GUEST_IDLE 0x0400 /* MSR_HV_GUEST_IDLE */ /* ECX: power management features */ #define CPUPM_HV_CSTATE_MASK 0x000f /* deepest C-state */ #define CPUPM_HV_C3_HPET 0x0010 /* C3 requires HPET */ Index: head/sys/dev/hyperv/vmbus/hyperv_var.h =================================================================== --- head/sys/dev/hyperv/vmbus/hyperv_var.h +++ head/sys/dev/hyperv/vmbus/hyperv_var.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _HYPERV_VAR_H_ +#define _HYPERV_VAR_H_ + +extern u_int hyperv_features; +extern u_int hyperv_recommends; + +#endif /* !_HYPERV_VAR_H_ */