Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:10.dhclient =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:10.dhclient (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:10.dhclient (revision 303965) @@ -0,0 +1,39 @@ +Index: sbin/dhclient/dhclient.c +=================================================================== +--- sbin/dhclient/dhclient.c (revision 302284) ++++ sbin/dhclient/dhclient.c (working copy) +@@ -2277,6 +2277,17 @@ script_set_env(struct client_state *clie + { + int i, j, namelen; + ++ /* No `` or $() command substitution allowed in environment values! */ ++ for (j=0; j < strlen(value); j++) ++ switch (value[j]) { ++ case '`': ++ case '$': ++ warning("illegal character (%c) in value '%s'", ++ value[j], value); ++ /* Ignore this option */ ++ return; ++ } ++ + namelen = strlen(name); + + for (i = 0; client->scriptEnv[i]; i++) +@@ -2313,16 +2324,6 @@ script_set_env(struct client_state *clie + strlen(value) + 1); + if (client->scriptEnv[i] == NULL) + error("script_set_env: no memory for variable assignment"); +- +- /* No `` or $() command substitution allowed in environment values! */ +- for (j=0; j < strlen(value); j++) +- switch (value[j]) { +- case '`': +- case '$': +- error("illegal character (%c) in value '%s'", value[j], +- value); +- /* not reached */ +- } + snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + + 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); + } Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:11.vmbus =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:11.vmbus (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:11.vmbus (revision 303965) @@ -0,0 +1,218 @@ +--- sys/dev/hyperv/vmbus/hv_channel.c.orig ++++ sys/dev/hyperv/vmbus/hv_channel.c +@@ -180,12 +180,12 @@ + if (user_data_len) + memcpy(open_msg->user_data, user_data, user_data_len); + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_INSERT_TAIL( + &hv_vmbus_g_connection.channel_msg_anchor, + open_info, + msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + ret = hv_vmbus_post_message( + open_msg, sizeof(hv_vmbus_channel_open_channel)); +@@ -212,12 +212,12 @@ + } + + cleanup: +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_REMOVE( + &hv_vmbus_g_connection.channel_msg_anchor, + open_info, + msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + sema_destroy(&open_info->wait_sema); + free(open_info, M_DEVBUF); + +@@ -401,13 +401,13 @@ + gpadl_msg->child_rel_id = channel->offer_msg.child_rel_id; + gpadl_msg->gpadl = next_gpadl_handle; + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_INSERT_TAIL( + &hv_vmbus_g_connection.channel_msg_anchor, + msg_info, + msg_list_entry); + +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + ret = hv_vmbus_post_message( + gpadl_msg, +@@ -446,10 +446,10 @@ + + cleanup: + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor, + msg_info, msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + sema_destroy(&msg_info->wait_sema); + free(msg_info, M_DEVBUF); +@@ -488,10 +488,10 @@ + msg->child_rel_id = channel->offer_msg.child_rel_id; + msg->gpadl = gpadl_handle; + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_INSERT_TAIL(&hv_vmbus_g_connection.channel_msg_anchor, + info, msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + ret = hv_vmbus_post_message(msg, + sizeof(hv_vmbus_channel_gpadl_teardown)); +@@ -504,10 +504,10 @@ + /* + * Received a torndown response + */ +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_REMOVE(&hv_vmbus_g_connection.channel_msg_anchor, + info, msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + sema_destroy(&info->wait_sema); + free(info, M_DEVBUF); + +--- sys/dev/hyperv/vmbus/hv_channel_mgmt.c.orig ++++ sys/dev/hyperv/vmbus/hv_channel_mgmt.c +@@ -567,7 +567,7 @@ + /* + * Find the open msg, copy the result and signal/unblock the wait event + */ +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + + TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, + msg_list_entry) { +@@ -585,7 +585,7 @@ + } + } + } +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + } + +@@ -609,7 +609,7 @@ + /* Find the establish msg, copy the result and signal/unblock + * the wait event + */ +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, + msg_list_entry) { + request_header = (hv_vmbus_channel_msg_header*) msg_info->msg; +@@ -628,7 +628,7 @@ + } + } + } +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + } + + /** +@@ -653,7 +653,7 @@ + * wait event. + */ + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + + TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, + msg_list_entry) { +@@ -673,7 +673,7 @@ + } + } + } +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + } + + /** +@@ -693,7 +693,7 @@ + + versionResponse = (hv_vmbus_channel_version_response*)hdr; + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, + msg_list_entry) { + requestHeader = (hv_vmbus_channel_msg_header*) msg_info->msg; +@@ -707,7 +707,7 @@ + sema_post(&msg_info->wait_sema); + } + } +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + } + +--- sys/dev/hyperv/vmbus/hv_connection.c.orig ++++ sys/dev/hyperv/vmbus/hv_connection.c +@@ -101,26 +101,26 @@ + * Add to list before we send the request since we may receive the + * response before returning from this routine + */ +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + + TAILQ_INSERT_TAIL( + &hv_vmbus_g_connection.channel_msg_anchor, + msg_info, + msg_list_entry); + +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + ret = hv_vmbus_post_message( + msg, + sizeof(hv_vmbus_channel_initiate_contact)); + + if (ret != 0) { +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_REMOVE( + &hv_vmbus_g_connection.channel_msg_anchor, + msg_info, + msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + return (ret); + } + +@@ -129,12 +129,12 @@ + */ + ret = sema_timedwait(&msg_info->wait_sema, 5 * hz); /* KYS 5 seconds */ + +- mtx_lock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); + TAILQ_REMOVE( + &hv_vmbus_g_connection.channel_msg_anchor, + msg_info, + msg_list_entry); +- mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock); ++ mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock); + + /** + * Check if successful +@@ -173,7 +173,7 @@ + + TAILQ_INIT(&hv_vmbus_g_connection.channel_msg_anchor); + mtx_init(&hv_vmbus_g_connection.channel_msg_lock, "vmbus channel msg", +- NULL, MTX_SPIN); ++ NULL, MTX_DEF); + + TAILQ_INIT(&hv_vmbus_g_connection.channel_anchor); + mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel", Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:12.hv_storvsc =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:12.hv_storvsc (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:12.hv_storvsc (revision 303965) @@ -0,0 +1,205 @@ +--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c.orig ++++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +@@ -81,12 +81,6 @@ + #define BLKVSC_MAX_IO_REQUESTS STORVSC_MAX_IO_REQUESTS + #define STORVSC_MAX_TARGETS (2) + +-#define STORVSC_WIN7_MAJOR 4 +-#define STORVSC_WIN7_MINOR 2 +- +-#define STORVSC_WIN8_MAJOR 5 +-#define STORVSC_WIN8_MINOR 1 +- + #define VSTOR_PKT_SIZE (sizeof(struct vstor_packet) - vmscsi_size_delta) + + #define HV_ALIGN(x, a) roundup2(x, a) +@@ -208,7 +202,7 @@ + * Sense buffer size changed in win8; have a run-time + * variable to track the size we should use. + */ +-static int sense_buffer_size; ++static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; + + /* + * The size of the vmscsi_request has changed in win8. The +@@ -218,9 +212,46 @@ + * Track the correct size we need to apply. + */ + static int vmscsi_size_delta; ++/* ++ * The storage protocol version is determined during the ++ * initial exchange with the host. It will indicate which ++ * storage functionality is available in the host. ++*/ ++static int vmstor_proto_version; ++ ++struct vmstor_proto { ++ int proto_version; ++ int sense_buffer_size; ++ int vmscsi_size_delta; ++}; + +-static int storvsc_current_major; +-static int storvsc_current_minor; ++static const struct vmstor_proto vmstor_proto_list[] = { ++ { ++ VMSTOR_PROTOCOL_VERSION_WIN10, ++ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, ++ 0 ++ }, ++ { ++ VMSTOR_PROTOCOL_VERSION_WIN8_1, ++ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, ++ 0 ++ }, ++ { ++ VMSTOR_PROTOCOL_VERSION_WIN8, ++ POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, ++ 0 ++ }, ++ { ++ VMSTOR_PROTOCOL_VERSION_WIN7, ++ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, ++ sizeof(struct vmscsi_win8_extension), ++ }, ++ { ++ VMSTOR_PROTOCOL_VERSION_WIN6, ++ PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, ++ sizeof(struct vmscsi_win8_extension), ++ } ++}; + + /* static functions */ + static int storvsc_probe(device_t dev); +@@ -435,7 +466,7 @@ + static int + hv_storvsc_channel_init(struct hv_device *dev) + { +- int ret = 0; ++ int ret = 0, i; + struct hv_storvsc_request *request; + struct vstor_packet *vstor_packet; + struct storvsc_softc *sc; +@@ -484,19 +515,20 @@ + goto cleanup; + } + +- /* reuse the packet for version range supported */ ++ for (i = 0; i < nitems(vmstor_proto_list); i++) { ++ /* reuse the packet for version range supported */ + +- memset(vstor_packet, 0, sizeof(struct vstor_packet)); +- vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION; +- vstor_packet->flags = REQUEST_COMPLETION_FLAG; ++ memset(vstor_packet, 0, sizeof(struct vstor_packet)); ++ vstor_packet->operation = VSTOR_OPERATION_QUERYPROTOCOLVERSION; ++ vstor_packet->flags = REQUEST_COMPLETION_FLAG; + +- vstor_packet->u.version.major_minor = +- VMSTOR_PROTOCOL_VERSION(storvsc_current_major, storvsc_current_minor); ++ vstor_packet->u.version.major_minor = ++ vmstor_proto_list[i].proto_version; + +- /* revision is only significant for Windows guests */ +- vstor_packet->u.version.revision = 0; ++ /* revision is only significant for Windows guests */ ++ vstor_packet->u.version.revision = 0; + +- ret = hv_vmbus_channel_send_packet( ++ ret = hv_vmbus_channel_send_packet( + dev->channel, + vstor_packet, + VSTOR_PKT_SIZE, +@@ -504,20 +536,34 @@ + HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, + HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); + +- if (ret != 0) +- goto cleanup; ++ if (ret != 0) ++ goto cleanup; + +- /* wait 5 seconds */ +- ret = sema_timedwait(&request->synch_sema, 5 * hz); ++ /* wait 5 seconds */ ++ ret = sema_timedwait(&request->synch_sema, 5 * hz); + +- if (ret) +- goto cleanup; ++ if (ret) ++ goto cleanup; + +- /* TODO: Check returned version */ +- if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || +- vstor_packet->status != 0) +- goto cleanup; ++ if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO) { ++ ret = EINVAL; ++ goto cleanup; ++ } ++ if (vstor_packet->status == 0) { ++ vmstor_proto_version = ++ vmstor_proto_list[i].proto_version; ++ sense_buffer_size = ++ vmstor_proto_list[i].sense_buffer_size; ++ vmscsi_size_delta = ++ vmstor_proto_list[i].vmscsi_size_delta; ++ break; ++ } ++ } + ++ if (vstor_packet->status != 0) { ++ ret = EINVAL; ++ goto cleanup; ++ } + /** + * Query channel properties + */ +@@ -916,19 +962,6 @@ + int ata_disk_enable = 0; + int ret = ENXIO; + +- if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 || +- hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) { +- sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; +- vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); +- storvsc_current_major = STORVSC_WIN7_MAJOR; +- storvsc_current_minor = STORVSC_WIN7_MINOR; +- } else { +- sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; +- vmscsi_size_delta = 0; +- storvsc_current_major = STORVSC_WIN8_MAJOR; +- storvsc_current_minor = STORVSC_WIN8_MINOR; +- } +- + switch (storvsc_get_storage_type(dev)) { + case DRIVER_BLKVSC: + if(bootverbose) +@@ -2064,6 +2097,13 @@ + ((ccb->ccb_h.flags & CAM_CDB_POINTER) ? + csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes); + if (cmd->opcode == INQUIRY && ++ /* ++ * XXX: Temporary work around disk hot plugin on win2k12r2, ++ * only filtering the invalid disk on win10 or 2016 server. ++ * So, the hot plugin on win10 and 2016 server needs ++ * to be fixed. ++ */ ++ vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN10 && + is_inquiry_valid( + (const struct scsi_inquiry_data *)csio->data_ptr) == 0) { + ccb->ccb_h.status |= CAM_DEV_NOT_THERE; +--- sys/dev/hyperv/storvsc/hv_vstorage.h.orig ++++ sys/dev/hyperv/storvsc/hv_vstorage.h +@@ -41,6 +41,11 @@ + #define VMSTOR_PROTOCOL_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ + (((MINOR_) & 0xff) )) + ++#define VMSTOR_PROTOCOL_VERSION_WIN6 VMSTOR_PROTOCOL_VERSION(2, 0) ++#define VMSTOR_PROTOCOL_VERSION_WIN7 VMSTOR_PROTOCOL_VERSION(4, 2) ++#define VMSTOR_PROTOCOL_VERSION_WIN8 VMSTOR_PROTOCOL_VERSION(5, 1) ++#define VMSTOR_PROTOCOL_VERSION_WIN8_1 VMSTOR_PROTOCOL_VERSION(6, 0) ++#define VMSTOR_PROTOCOL_VERSION_WIN10 VMSTOR_PROTOCOL_VERSION(6, 2) + /* + * Invalid version. + */ Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:13.vmbus =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:13.vmbus (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:13.vmbus (revision 303965) @@ -0,0 +1,155 @@ +--- sys/dev/hyperv/vmbus/hv_hv.c.orig ++++ sys/dev/hyperv/vmbus/hv_hv.c +@@ -33,6 +33,7 @@ + __FBSDID("$FreeBSD$"); + + #include ++#include + #include + #include + #include +@@ -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 { Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:14.hv_storvsc =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:14.hv_storvsc (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:14.hv_storvsc (revision 303965) @@ -0,0 +1,50 @@ +--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c.orig ++++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +@@ -1273,6 +1273,7 @@ + } + #endif /* HVS_TIMEOUT_TEST */ + ++#ifdef notyet + /** + * @brief timeout handler for requests + * +@@ -1320,6 +1321,7 @@ + storvsc_timeout_test(reqp, MODE_SELECT_10, 1); + #endif + } ++#endif + + /** + * @brief StorVSC device poll function +@@ -1472,6 +1474,7 @@ + return; + } + ++#ifdef notyet + if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { + callout_init(&reqp->callout, CALLOUT_MPSAFE); + callout_reset_sbt(&reqp->callout, +@@ -1491,6 +1494,7 @@ + } + #endif /* HVS_TIMEOUT_TEST */ + } ++#endif + + if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) { + xpt_print(ccb->ccb_h.path, +@@ -2039,6 +2043,7 @@ + mtx_unlock(&sc->hs_lock); + } + ++#ifdef notyet + /* + * callout_drain() will wait for the timer handler to finish + * if it is running. So we don't need any lock to synchronize +@@ -2049,6 +2054,7 @@ + if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) { + callout_drain(&reqp->callout); + } ++#endif + + ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + ccb->ccb_h.status &= ~CAM_STATUS_MASK; Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:15.vmbus =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:15.vmbus (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:15.vmbus (revision 303965) @@ -0,0 +1,68 @@ +--- sys/dev/hyperv/vmbus/hv_connection.c.orig ++++ sys/dev/hyperv/vmbus/hv_connection.c +@@ -476,31 +476,35 @@ + /** + * Send a msg on the vmbus's message connection + */ +-int hv_vmbus_post_message(void *buffer, size_t bufferLen) { +- int ret = 0; ++int hv_vmbus_post_message(void *buffer, size_t bufferLen) ++{ + hv_vmbus_connection_id connId; +- unsigned retries = 0; +- +- /* NetScaler delays from previous code were consolidated here */ +- static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000}; +- +- /* for(each entry in delayAmount) try to post message, +- * delay a little bit before retrying ++ sbintime_t time = SBT_1MS; ++ int retries; ++ int ret; ++ ++ connId.as_uint32_t = 0; ++ connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID; ++ ++ /* ++ * We retry to cope with transient failures caused by host side's ++ * insufficient resources. 20 times should suffice in practice. + */ +- for (retries = 0; +- retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) { +- connId.as_uint32_t = 0; +- connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID; +- ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen); +- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) +- break; +- /* TODO: KYS We should use a blocking wait call */ +- DELAY(delayAmount[retries]); ++ for (retries = 0; retries < 20; retries++) { ++ ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, ++ bufferLen); ++ if (ret == HV_STATUS_SUCCESS) ++ return (0); ++ ++ pause_sbt("pstmsg", time, 0, C_HARDCLOCK); ++ if (time < SBT_1S * 2) ++ time *= 2; + } + +- KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n")); ++ KASSERT(ret == HV_STATUS_SUCCESS, ++ ("Error VMBUS: Message Post Failed, ret=%d\n", ret)); + +- return (ret); ++ return (EAGAIN); + } + + /** +--- sys/dev/hyperv/vmbus/hv_vmbus_priv.h.orig ++++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h +@@ -70,6 +70,7 @@ + * You did not supply enough message buffers to send a message. + */ + ++#define HV_STATUS_SUCCESS ((uint16_t)0) + #define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013) + + typedef void (*hv_vmbus_channel_callback)(void *context); Index: user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:16.hv_storvsc =================================================================== --- user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:16.hv_storvsc (nonexistent) +++ user/cperciva/freebsd-update-build/patches/10.3-RELEASE/7-EN-16:16.hv_storvsc (revision 303965) @@ -0,0 +1,165 @@ +--- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c.orig ++++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +@@ -805,6 +805,13 @@ + + vm_srb = &vstor_packet->u.vm_srb; + ++ /* ++ * Copy some fields of the host's response into the request structure, ++ * because the fields will be used later in storvsc_io_done(). ++ */ ++ request->vstor_packet.u.vm_srb.scsi_status = vm_srb->scsi_status; ++ request->vstor_packet.u.vm_srb.transfer_len = vm_srb->transfer_len; ++ + if (((vm_srb->scsi_status & 0xFF) == SCSI_STATUS_CHECK_COND) && + (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)) { + /* Autosense data available */ +@@ -1939,62 +1946,24 @@ + } + + /* +- * Modified based on scsi_print_inquiry which is responsible to +- * print the detail information for scsi_inquiry_data. +- * ++ * SCSI Inquiry checks qualifier and type. ++ * If qualifier is 011b, means the device server is not capable ++ * of supporting a peripheral device on this logical unit, and ++ * the type should be set to 1Fh. ++ * + * Return 1 if it is valid, 0 otherwise. + */ + static inline int + is_inquiry_valid(const struct scsi_inquiry_data *inq_data) + { + uint8_t type; +- char vendor[16], product[48], revision[16]; +- +- /* +- * Check device type and qualifier +- */ +- if (!(SID_QUAL_IS_VENDOR_UNIQUE(inq_data) || +- SID_QUAL(inq_data) == SID_QUAL_LU_CONNECTED)) ++ if (SID_QUAL(inq_data) != SID_QUAL_LU_CONNECTED) { + return (0); +- ++ } + type = SID_TYPE(inq_data); +- switch (type) { +- case T_DIRECT: +- case T_SEQUENTIAL: +- case T_PRINTER: +- case T_PROCESSOR: +- case T_WORM: +- case T_CDROM: +- case T_SCANNER: +- case T_OPTICAL: +- case T_CHANGER: +- case T_COMM: +- case T_STORARRAY: +- case T_ENCLOSURE: +- case T_RBC: +- case T_OCRW: +- case T_OSD: +- case T_ADC: +- break; +- case T_NODEVICE: +- default: ++ if (type == T_NODEVICE) { + return (0); + } +- +- /* +- * Check vendor, product, and revision +- */ +- cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), +- sizeof(vendor)); +- cam_strvis(product, inq_data->product, sizeof(inq_data->product), +- sizeof(product)); +- cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), +- sizeof(revision)); +- if (strlen(vendor) == 0 || +- strlen(product) == 0 || +- strlen(revision) == 0) +- return (0); +- + return (1); + } + +@@ -2071,7 +2040,6 @@ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + if (vm_srb->scsi_status == SCSI_STATUS_OK) { + const struct scsi_generic *cmd; +- + /* + * Check whether the data for INQUIRY cmd is valid or + * not. Windows 10 and Windows 2016 send all zero +@@ -2080,23 +2048,59 @@ + cmd = (const struct scsi_generic *) + ((ccb->ccb_h.flags & CAM_CDB_POINTER) ? + csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes); +- if (cmd->opcode == INQUIRY && +- /* +- * XXX: Temporary work around disk hot plugin on win2k12r2, +- * only filtering the invalid disk on win10 or 2016 server. +- * So, the hot plugin on win10 and 2016 server needs +- * to be fixed. ++ if (cmd->opcode == INQUIRY) { ++ /* ++ * The host of Windows 10 or 2016 server will response ++ * the inquiry request with invalid data for unexisted device: ++ [0x7f 0x0 0x5 0x2 0x1f ... ] ++ * But on windows 2012 R2, the response is: ++ [0x7f 0x0 0x0 0x0 0x0 ] ++ * That is why here wants to validate the inquiry response. ++ * The validation will skip the INQUIRY whose response is short, ++ * which is less than SHORT_INQUIRY_LENGTH (36). ++ * ++ * For more information about INQUIRY, please refer to: ++ * ftp://ftp.avc-pioneer.com/Mtfuji_7/Proposal/Jun09/INQUIRY.pdf + */ +- vmstor_proto_version == VMSTOR_PROTOCOL_VERSION_WIN10 && +- is_inquiry_valid( +- (const struct scsi_inquiry_data *)csio->data_ptr) == 0) { ++ const struct scsi_inquiry_data *inq_data = ++ (const struct scsi_inquiry_data *)csio->data_ptr; ++ uint8_t* resp_buf = (uint8_t*)csio->data_ptr; ++ /* Get the buffer length reported by host */ ++ int resp_xfer_len = vm_srb->transfer_len; ++ /* Get the available buffer length */ ++ int resp_buf_len = resp_xfer_len >= 5 ? resp_buf[4] + 5 : 0; ++ int data_len = (resp_buf_len < resp_xfer_len) ? resp_buf_len : resp_xfer_len; ++ if (data_len < SHORT_INQUIRY_LENGTH) { ++ ccb->ccb_h.status |= CAM_REQ_CMP; ++ if (bootverbose && data_len >= 5) { ++ mtx_lock(&sc->hs_lock); ++ xpt_print(ccb->ccb_h.path, ++ "storvsc skips the validation for short inquiry (%d)" ++ " [%x %x %x %x %x]\n", ++ data_len,resp_buf[0],resp_buf[1],resp_buf[2], ++ resp_buf[3],resp_buf[4]); ++ mtx_unlock(&sc->hs_lock); ++ } ++ } else if (is_inquiry_valid(inq_data) == 0) { + ccb->ccb_h.status |= CAM_DEV_NOT_THERE; ++ if (bootverbose && data_len >= 5) { ++ mtx_lock(&sc->hs_lock); ++ xpt_print(ccb->ccb_h.path, ++ "storvsc uninstalled invalid device" ++ " [%x %x %x %x %x]\n", ++ resp_buf[0],resp_buf[1],resp_buf[2],resp_buf[3],resp_buf[4]); ++ mtx_unlock(&sc->hs_lock); ++ } ++ } else { ++ ccb->ccb_h.status |= CAM_REQ_CMP; + if (bootverbose) { + mtx_lock(&sc->hs_lock); + xpt_print(ccb->ccb_h.path, +- "storvsc uninstalled device\n"); ++ "storvsc has passed inquiry response (%d) validation\n", ++ data_len); + mtx_unlock(&sc->hs_lock); + } ++ } + } else { + ccb->ccb_h.status |= CAM_REQ_CMP; + }