Author: glebius
Date: Fri Aug 12 04:01:16 2016
New Revision: 303984
URL: https://svnweb.freebsd.org/changeset/base/303984

Log:
  Release 6 errata notices for 10.3-RELEASE, all related to Microsoft Hyper-V.
  
  Submitted by: Dexuan Cui <decui microsoft.com>, gjb
  Approved by:  so

Modified:
  releng/10.3/UPDATING
  releng/10.3/sbin/dhclient/dhclient.c
  releng/10.3/sys/conf/newvers.sh
  releng/10.3/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
  releng/10.3/sys/dev/hyperv/storvsc/hv_vstorage.h
  releng/10.3/sys/dev/hyperv/vmbus/hv_channel.c
  releng/10.3/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
  releng/10.3/sys/dev/hyperv/vmbus/hv_connection.c
  releng/10.3/sys/dev/hyperv/vmbus/hv_hv.c
  releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
Directory Properties:
  releng/10.3/   (props changed)

Modified: releng/10.3/UPDATING
==============================================================================
--- releng/10.3/UPDATING        Fri Aug 12 03:47:38 2016        (r303983)
+++ releng/10.3/UPDATING        Fri Aug 12 04:01:16 2016        (r303984)
@@ -16,6 +16,22 @@ from older versions of FreeBSD, try WITH
 stable/10, and then rebuild without this option. The bootstrap process from
 older version of current is a bit fragile.
 
+20160811       p7      FreeBSD-EN-16:10.dhclient
+                       FreeBSD-EN-16:11.vmbus
+                       FreeBSD-EN-16:12.hv_storvsc
+                       FreeBSD-EN-16:13.vmbus
+                       FreeBSD-EN-16:14.hv_storvsc
+                       FreeBSD-EN-16:15.vmbus
+                       FreeBSD-EN-16:16.hv_storvsc
+
+       Fix handling of unknown options from a DHCP server. [EN-16:10]
+       Fix a panic in hv_vmbus(4). [EN-16:11]
+       Fix missing hotplugged disk in hv_storvsc(4). [EN-16:12]
+       Fix the timecounter emulation in hv_vmbus(4). [EN-16:13]
+       Fix callout(9) handling in hv_storvsc(4). [EN-16:14]
+       Fix memory allocation issues in hv_vmbus(4). [EN-16:15]
+       Fix SCSI command handling in hv_storvsc(4). [EN-16:16]
+
 20160725       p6      FreeBSD-SA-16:25.bspatch
                        FreeBSD-EN-16:09.freebsd-update
 

Modified: releng/10.3/sbin/dhclient/dhclient.c
==============================================================================
--- releng/10.3/sbin/dhclient/dhclient.c        Fri Aug 12 03:47:38 2016        
(r303983)
+++ releng/10.3/sbin/dhclient/dhclient.c        Fri Aug 12 04:01:16 2016        
(r303984)
@@ -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);
 }

Modified: releng/10.3/sys/conf/newvers.sh
==============================================================================
--- releng/10.3/sys/conf/newvers.sh     Fri Aug 12 03:47:38 2016        
(r303983)
+++ releng/10.3/sys/conf/newvers.sh     Fri Aug 12 04:01:16 2016        
(r303984)
@@ -32,7 +32,7 @@
 
 TYPE="FreeBSD"
 REVISION="10.3"
-BRANCH="RELEASE-p6"
+BRANCH="RELEASE-p7"
 if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
        BRANCH=${BRANCH_OVERRIDE}
 fi

Modified: releng/10.3/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- releng/10.3/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Fri Aug 12 
03:47:38 2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c Fri Aug 12 
04:01:16 2016        (r303984)
@@ -81,12 +81,6 @@ __FBSDID("$FreeBSD$");
 #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 @@ static struct storvsc_driver_props g_drv
  * 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 @@ static int sense_buffer_size;
  * 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 @@ storvsc_send_multichannel_request(struct
 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 @@ hv_storvsc_channel_init(struct hv_device
                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_storvsc_channel_init(struct hv_device
                        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
         */
@@ -767,6 +813,13 @@ hv_storvsc_on_iocompletion(struct storvs
 
        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 */
@@ -916,19 +969,6 @@ storvsc_probe(device_t dev)
        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)
@@ -1273,6 +1313,7 @@ storvsc_timeout_test(struct hv_storvsc_r
 }
 #endif /* HVS_TIMEOUT_TEST */
 
+#ifdef notyet
 /**
  * @brief timeout handler for requests
  *
@@ -1320,6 +1361,7 @@ storvsc_timeout(void *arg)
        storvsc_timeout_test(reqp, MODE_SELECT_10, 1);
 #endif
 }
+#endif
 
 /**
  * @brief StorVSC device poll function
@@ -1472,6 +1514,7 @@ storvsc_action(struct cam_sim *sim, unio
                        return;
                }
 
+#ifdef notyet
                if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
                        callout_init(&reqp->callout, CALLOUT_MPSAFE);
                        callout_reset_sbt(&reqp->callout,
@@ -1491,6 +1534,7 @@ storvsc_action(struct cam_sim *sim, unio
                        }
 #endif /* HVS_TIMEOUT_TEST */
                }
+#endif
 
                if ((res = hv_storvsc_io_request(sc->hs_dev, reqp)) != 0) {
                        xpt_print(ccb->ccb_h.path,
@@ -1924,62 +1968,24 @@ create_storvsc_request(union ccb *ccb, s
 }
 
 /*
- * 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);
 }
 
@@ -2039,6 +2045,7 @@ storvsc_io_done(struct hv_storvsc_reques
                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,12 +2056,12 @@ storvsc_io_done(struct hv_storvsc_reques
        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;
        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
@@ -2063,16 +2070,59 @@ storvsc_io_done(struct hv_storvsc_reques
                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 &&
-                   is_inquiry_valid(
-                   (const struct scsi_inquiry_data *)csio->data_ptr) == 0) {
+               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
+                    */
+                   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;
                }

Modified: releng/10.3/sys/dev/hyperv/storvsc/hv_vstorage.h
==============================================================================
--- releng/10.3/sys/dev/hyperv/storvsc/hv_vstorage.h    Fri Aug 12 03:47:38 
2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/storvsc/hv_vstorage.h    Fri Aug 12 04:01:16 
2016        (r303984)
@@ -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.
  */

Modified: releng/10.3/sys/dev/hyperv/vmbus/hv_channel.c
==============================================================================
--- releng/10.3/sys/dev/hyperv/vmbus/hv_channel.c       Fri Aug 12 03:47:38 
2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/vmbus/hv_channel.c       Fri Aug 12 04:01:16 
2016        (r303984)
@@ -180,12 +180,12 @@ hv_vmbus_channel_open(
        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 @@ hv_vmbus_channel_open(
        }
 
        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 @@ hv_vmbus_channel_establish_gpadl(
        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 @@ hv_vmbus_channel_establish_gpadl(
 
 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 @@ hv_vmbus_channel_teardown_gpdal(
        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 @@ cleanup:
        /*
         * 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);
 

Modified: releng/10.3/sys/dev/hyperv/vmbus/hv_channel_mgmt.c
==============================================================================
--- releng/10.3/sys/dev/hyperv/vmbus/hv_channel_mgmt.c  Fri Aug 12 03:47:38 
2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/vmbus/hv_channel_mgmt.c  Fri Aug 12 04:01:16 
2016        (r303984)
@@ -567,7 +567,7 @@ vmbus_channel_on_open_result(hv_vmbus_ch
        /*
         * 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 @@ vmbus_channel_on_open_result(hv_vmbus_ch
                }
            }
        }
-       mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+       mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
 
 }
 
@@ -609,7 +609,7 @@ vmbus_channel_on_gpadl_created(hv_vmbus_
        /* 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 @@ vmbus_channel_on_gpadl_created(hv_vmbus_
                }
            }
        }
-       mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+       mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
 }
 
 /**
@@ -653,7 +653,7 @@ vmbus_channel_on_gpadl_torndown(hv_vmbus
         * 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 @@ vmbus_channel_on_gpadl_torndown(hv_vmbus
                }
            }
        }
-    mtx_unlock_spin(&hv_vmbus_g_connection.channel_msg_lock);
+    mtx_unlock(&hv_vmbus_g_connection.channel_msg_lock);
 }
 
 /**
@@ -693,7 +693,7 @@ vmbus_channel_on_version_response(hv_vmb
 
        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 @@ vmbus_channel_on_version_response(hv_vmb
                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);
 
 }
 

Modified: releng/10.3/sys/dev/hyperv/vmbus/hv_connection.c
==============================================================================
--- releng/10.3/sys/dev/hyperv/vmbus/hv_connection.c    Fri Aug 12 03:47:38 
2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/vmbus/hv_connection.c    Fri Aug 12 04:01:16 
2016        (r303984)
@@ -101,26 +101,26 @@ hv_vmbus_negotiate_version(hv_vmbus_chan
         * 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 @@ hv_vmbus_negotiate_version(hv_vmbus_chan
         */
        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 @@ hv_vmbus_connect(void) {
 
        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",
@@ -476,31 +476,35 @@ hv_vmbus_on_events(void *arg) 
 /**
  * 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;
+       sbintime_t time = SBT_1MS;
+       int retries;
+       int ret;
 
-       /* NetScaler delays from previous code were consolidated here */
-       static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
+       connId.as_uint32_t = 0;
+       connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
 
-       /* for(each entry in delayAmount) try to post message,
-        *  delay a little bit before retrying
+       /*
+        * 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);
 }
 
 /**

Modified: releng/10.3/sys/dev/hyperv/vmbus/hv_hv.c
==============================================================================
--- releng/10.3/sys/dev/hyperv/vmbus/hv_hv.c    Fri Aug 12 03:47:38 2016        
(r303983)
+++ releng/10.3/sys/dev/hyperv/vmbus/hv_hv.c    Fri Aug 12 04:01:16 2016        
(r303984)
@@ -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
  */
@@ -211,8 +215,6 @@ hv_vmbus_init(void) 
 
        hv_vmbus_g_context.hypercall_page = virt_addr;
 
-       tc_init(&hv_timecounter); /* register virtual timecount */
-
        hv_et_init();
        
        return (0);
@@ -427,3 +429,93 @@ 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;
+
+       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);

Modified: releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
==============================================================================
--- releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h    Fri Aug 12 03:47:38 
2016        (r303983)
+++ releng/10.3/sys/dev/hyperv/vmbus/hv_vmbus_priv.h    Fri Aug 12 04:01:16 
2016        (r303984)
@@ -70,6 +70,7 @@ typedef uint16_t hv_vmbus_status;
  *    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);
@@ -471,10 +472,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
  */
@@ -628,6 +636,9 @@ typedef enum {
 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 {
_______________________________________________
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"

Reply via email to