Index: sys/dev/hyperv/include/hyperv.h =================================================================== --- sys/dev/hyperv/include/hyperv.h +++ sys/dev/hyperv/include/hyperv.h @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -120,21 +121,7 @@ ((HV_ALIGN_UP(addr+len, PAGE_SIZE) - \ HV_ALIGN_DOWN(addr, PAGE_SIZE)) >> PAGE_SHIFT ) -typedef struct hv_guid { - unsigned char data[16]; -} __packed hv_guid; - -#define HV_NIC_GUID \ - .data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \ - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} - -#define HV_IDE_GUID \ - .data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, \ - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5} - -#define HV_SCSI_GUID \ - .data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, \ - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f} +typedef unsigned char hv_guid[16]; /* * At the center of the Channel Management library is @@ -837,8 +824,8 @@ } typedef struct hv_device { - hv_guid class_id; - hv_guid device_id; + struct uuid class_id; + struct uuid device_id; device_t device; hv_vmbus_channel* channel; } hv_device; @@ -865,6 +852,7 @@ uint32_t recv_ring_buffer_size, void* user_data, uint32_t user_data_len, + boolean_t is_perf_channel, hv_vmbus_pfn_channel_callback pfn_on_channel_callback, void* context); Index: sys/dev/hyperv/netvsc/hv_net_vsc.c =================================================================== --- sys/dev/hyperv/netvsc/hv_net_vsc.c +++ sys/dev/hyperv/netvsc/hv_net_vsc.c @@ -679,7 +679,7 @@ */ ret = hv_vmbus_channel_open(device->channel, NETVSC_DEVICE_RING_BUFFER_SIZE, NETVSC_DEVICE_RING_BUFFER_SIZE, - NULL, 0, hv_nv_on_channel_callback, device); + NULL, 0, TRUE, hv_nv_on_channel_callback, device); if (ret != 0) goto cleanup; Index: sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c =================================================================== --- sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -330,9 +330,9 @@ } /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ -static const hv_guid g_net_vsc_device_type = { - .data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, - 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} +static const struct uuid g_net_vsc_device_type = { + 0xF8615163, 0xDF3E, 0x46c5, 0x91, 0x3F, + {0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} }; /* @@ -345,7 +345,7 @@ const char *p; p = vmbus_get_type(dev); - if (!memcmp(p, &g_net_vsc_device_type.data, sizeof(hv_guid))) { + if (!memcmp(p, &g_net_vsc_device_type, sizeof(struct uuid))) { device_set_desc(dev, "Synthetic Network Interface"); if (bootverbose) printf("Netvsc probe... DONE \n"); Index: sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c =================================================================== --- sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c +++ sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c @@ -184,15 +184,15 @@ #define HV_STORAGE_SUPPORTS_MULTI_CHANNEL 0x1 /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ -static const hv_guid gStorVscDeviceType={ - .data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, - 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f} +static const struct uuid gStorVscDeviceType={ + 0xba6163d9, 0x04a1, 0x4d29, 0xb6, 0x05, + {0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f} }; /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ -static const hv_guid gBlkVscDeviceType={ - .data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, - 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5} +static const struct uuid gBlkVscDeviceType={ + 0x32412632, 0x86cb, 0x44a2, 0x9b, 0x5c, + {0x50,0xd1,0x41,0x73,0x54,0xf5} }; static struct storvsc_driver_props g_drv_props_table[] = { @@ -349,6 +349,7 @@ sc->hs_drv_props->drv_ringbuffer_size, (void *)&props, sizeof(struct vmstor_chan_props), + TRUE, hv_storvsc_on_channel_callback, new_channel); @@ -624,6 +625,7 @@ sc->hs_drv_props->drv_ringbuffer_size, (void *)&props, sizeof(struct vmstor_chan_props), + TRUE, hv_storvsc_on_channel_callback, dev->channel); @@ -2134,9 +2136,9 @@ { const char *p = vmbus_get_type(dev); - if (!memcmp(p, &gBlkVscDeviceType, sizeof(hv_guid))) { + if (!memcmp(p, &gBlkVscDeviceType, sizeof(struct uuid))) { return DRIVER_BLKVSC; - } else if (!memcmp(p, &gStorVscDeviceType, sizeof(hv_guid))) { + } else if (!memcmp(p, &gStorVscDeviceType, sizeof(struct uuid))) { return DRIVER_STORVSC; } return (DRIVER_UNKNOWN); Index: sys/dev/hyperv/utilities/hv_heartbeat.c =================================================================== --- sys/dev/hyperv/utilities/hv_heartbeat.c +++ sys/dev/hyperv/utilities/hv_heartbeat.c @@ -38,9 +38,10 @@ #include "hv_util.h" /* Heartbeat Service */ -static hv_guid service_guid = { .data = - {0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, - 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} }; +static struct uuid service_guid = { + 0x57164f39, 0x9115, 0x4e78, 0xab, 0x55, + {0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d} +}; /** * Process heartbeat message @@ -94,7 +95,7 @@ hv_heartbeat_probe(device_t dev) { const char *p = vmbus_get_type(dev); - if (!memcmp(p, &service_guid, sizeof(hv_guid))) { + if (!memcmp(p, &service_guid, sizeof(struct uuid))) { device_set_desc(dev, "Hyper-V Heartbeat Service"); return BUS_PROBE_DEFAULT; } Index: sys/dev/hyperv/utilities/hv_kvp.c =================================================================== --- sys/dev/hyperv/utilities/hv_kvp.c +++ sys/dev/hyperv/utilities/hv_kvp.c @@ -86,9 +86,10 @@ log(LOG_INFO, "hv_kvp: " __VA_ARGS__); \ } while (0) -static hv_guid service_guid = { .data = - {0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6} }; +static struct uuid service_guid = { + 0xa9a0f4e7, 0x5a45, 0x4d96, 0xb8, 0x27, + {0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6} +}; /* character device prototypes */ static d_open_t hv_kvp_dev_open; @@ -304,28 +305,11 @@ { int err_ip, err_subnet, err_gway, err_dns, err_adap; int UNUSED_FLAG = 1; - int guid_index; struct hv_device *hv_dev; /* GUID Data Structure */ hn_softc_t *sc; /* hn softc structure */ char if_name[4]; - unsigned char guid_instance[40]; - char *guid_data = NULL; - char buf[39]; - - struct guid_extract { - char a1[2]; - char a2[2]; - char a3[2]; - char a4[2]; - char b1[2]; - char b2[2]; - char c1[2]; - char c2[2]; - char d[4]; - char e[12]; - }; - - struct guid_extract *id; + char buf[40]; + device_t *devs; int devcnt; @@ -352,19 +336,10 @@ /* Trying to find GUID of Network Device */ hv_dev = sc->hn_dev_obj; - for (guid_index = 0; guid_index < 16; guid_index++) { - sprintf(&guid_instance[guid_index * 2], "%02x", - hv_dev->device_id.data[guid_index]); - } - - guid_data = (char *)guid_instance; - id = (struct guid_extract *)guid_data; - snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}", - id->a4, id->a3, id->a2, id->a1, - id->b2, id->b1, id->c2, id->c1, id->d, id->e); - guid_data = NULL; + snprintf_uuid(buf, sizeof(buf), &hv_dev->device_id); sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt])); + printf("try to match %s =? %s\n", buf, (char *)umsg->body.kvp_ip_val.adapter_id); if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) { strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name); break; @@ -890,7 +865,7 @@ hv_kvp_probe(device_t dev) { const char *p = vmbus_get_type(dev); - if (!memcmp(p, &service_guid, sizeof(hv_guid))) { + if (!memcmp(p, &service_guid, sizeof(struct uuid))) { device_set_desc(dev, "Hyper-V KVP Service"); return BUS_PROBE_DEFAULT; } Index: sys/dev/hyperv/utilities/hv_shutdown.c =================================================================== --- sys/dev/hyperv/utilities/hv_shutdown.c +++ sys/dev/hyperv/utilities/hv_shutdown.c @@ -42,9 +42,10 @@ #include #include "hv_util.h" -static hv_guid service_guid = { .data = - {0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, - 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB} }; +static struct uuid service_guid = { + 0x0e0b6031, 0x5213, 0x4934, 0x81, 0x8B, + {0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB} +}; /** * Shutdown @@ -116,7 +117,7 @@ hv_shutdown_probe(device_t dev) { const char *p = vmbus_get_type(dev); - if (!memcmp(p, &service_guid, sizeof(hv_guid))) { + if (!memcmp(p, &service_guid, sizeof(struct uuid))) { device_set_desc(dev, "Hyper-V Shutdown Service"); return BUS_PROBE_DEFAULT; } Index: sys/dev/hyperv/utilities/hv_timesync.c =================================================================== --- sys/dev/hyperv/utilities/hv_timesync.c +++ sys/dev/hyperv/utilities/hv_timesync.c @@ -54,9 +54,10 @@ } time_sync_data; /* Time Synch Service */ -static hv_guid service_guid = {.data = - {0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, - 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf } }; +static struct uuid service_guid = { + 0x9527e630, 0xd0ae, 0x497b, 0xad, 0xce, + {0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf} +}; struct hv_ictimesync_data { uint64_t parenttime; @@ -171,7 +172,7 @@ hv_timesync_probe(device_t dev) { const char *p = vmbus_get_type(dev); - if (!memcmp(p, &service_guid, sizeof(hv_guid))) { + if (!memcmp(p, &service_guid, sizeof(struct uuid))) { device_set_desc(dev, "Hyper-V Time Synch Service"); return BUS_PROBE_DEFAULT; } Index: sys/dev/hyperv/utilities/hv_util.c =================================================================== --- sys/dev/hyperv/utilities/hv_util.c +++ sys/dev/hyperv/utilities/hv_util.c @@ -94,7 +94,7 @@ hv_set_channel_read_state(hv_dev->channel, FALSE); ret = hv_vmbus_channel_open(hv_dev->channel, 4 * PAGE_SIZE, - 4 * PAGE_SIZE, NULL, 0, + 4 * PAGE_SIZE, NULL, 0, FALSE, softc->callback, softc); if (ret) Index: sys/dev/hyperv/vmbus/hv_channel.c =================================================================== --- sys/dev/hyperv/vmbus/hv_channel.c +++ sys/dev/hyperv/vmbus/hv_channel.c @@ -53,6 +53,11 @@ static void vmbus_channel_set_event(hv_vmbus_channel* channel); static void VmbusProcessChannelEvent(void* channel, int pending); +/* + * We use this static number to distribute the channel interrupt load. + */ +static uint32_t next_vcpu; + /** * @brief Trigger an event notification on the specified channel */ @@ -80,6 +85,40 @@ } /** + * Starting with Win8, we can statically distribute the incoming + * channel interrupt load by binding a channel to VCPU. We + * implement here a simple round robin scheme for distributing + * the interrupt load. + * We will bind channels that are not performance critical to cpu 0 and + * performance critical channels (IDE, SCSI and Network) will be uniformly + * distributed across all available CPUs. + */ +static void +vmbus_channel_select_cpu(hv_vmbus_channel *channel, boolean_t is_perf_channel) +{ + uint32_t current_cpu; + + if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) || + (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) || + (!is_perf_channel)) { + /* Host's view of guest cpu */ + channel->target_vcpu = 0; + /* Guest's own view of cpu */ + channel->target_cpu = 0; + return; + } + + /* mp_ncpus should have the number cpus currently online */ + current_cpu = (++next_vcpu % mp_ncpus); + channel->target_cpu = current_cpu; + channel->target_vcpu = + hv_vmbus_g_context.hv_vcpu_index[current_cpu]; + if (bootverbose) + printf("VMBUS: Total online cpus %d, assign perf channel " + "to vcpu %d, cpu %d\n", mp_ncpus, channel->target_vcpu, + current_cpu); +} +/** * @brief Open the specified channel */ int @@ -89,6 +128,7 @@ uint32_t recv_ring_buffer_size, void* user_data, uint32_t user_data_len, + boolean_t is_perf_channel, hv_vmbus_pfn_channel_callback pfn_on_channel_callback, void* context) { @@ -110,6 +150,7 @@ } mtx_unlock(&new_channel->sc_lock); + vmbus_channel_select_cpu(new_channel, is_perf_channel); new_channel->on_channel_callback = pfn_on_channel_callback; new_channel->channel_callback_context = context; Index: sys/dev/hyperv/vmbus/hv_channel_mgmt.c =================================================================== --- sys/dev/hyperv/vmbus/hv_channel_mgmt.c +++ sys/dev/hyperv/vmbus/hv_channel_mgmt.c @@ -171,6 +171,8 @@ hv_vmbus_channel* channel; int ret; uint32_t relid; + struct uuid type_guid; + struct uuid instance_guid; f_new = TRUE; channel = NULL; @@ -186,10 +188,10 @@ { if (memcmp(&channel->offer_msg.offer.interface_type, &new_channel->offer_msg.offer.interface_type, - sizeof(hv_guid)) == 0 && + sizeof(struct uuid)) == 0 && memcmp(&channel->offer_msg.offer.interface_instance, &new_channel->offer_msg.offer.interface_instance, - sizeof(hv_guid)) == 0) { + sizeof(struct uuid)) == 0) { f_new = FALSE; break; } @@ -256,9 +258,10 @@ * (We need to set the device field before calling * hv_vmbus_child_device_add()) */ + le_uuid_dec(new_channel->offer_msg.offer.interface_type, &type_guid); + le_uuid_dec(new_channel->offer_msg.offer.interface_instance, &instance_guid); new_channel->device = hv_vmbus_child_device_create( - new_channel->offer_msg.offer.interface_type, - new_channel->offer_msg.offer.interface_instance, new_channel); + &type_guid, &instance_guid, new_channel); /* * Add the new device to the bus. This will kick off device-driver @@ -278,72 +281,6 @@ } /** - * Array of device guids that are performance critical. We try to distribute - * the interrupt load for these devices across all online cpus. - */ -static const hv_guid high_perf_devices[] = { - {HV_NIC_GUID, }, - {HV_IDE_GUID, }, - {HV_SCSI_GUID, }, -}; - -enum { - PERF_CHN_NIC = 0, - PERF_CHN_IDE, - PERF_CHN_SCSI, - MAX_PERF_CHN, -}; - -/* - * We use this static number to distribute the channel interrupt load. - */ -static uint32_t next_vcpu; - -/** - * Starting with Win8, we can statically distribute the incoming - * channel interrupt load by binding a channel to VCPU. We - * implement here a simple round robin scheme for distributing - * the interrupt load. - * We will bind channels that are not performance critical to cpu 0 and - * performance critical channels (IDE, SCSI and Network) will be uniformly - * distributed across all available CPUs. - */ -static void -vmbus_channel_select_cpu(hv_vmbus_channel *channel, hv_guid *guid) -{ - uint32_t current_cpu; - int i; - boolean_t is_perf_channel = FALSE; - - for (i = PERF_CHN_NIC; i < MAX_PERF_CHN; i++) { - if (memcmp(guid->data, high_perf_devices[i].data, - sizeof(hv_guid)) == 0) { - is_perf_channel = TRUE; - break; - } - } - - if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) || - (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) || - (!is_perf_channel)) { - /* Host's view of guest cpu */ - channel->target_vcpu = 0; - /* Guest's own view of cpu */ - channel->target_cpu = 0; - return; - } - /* mp_ncpus should have the number cpus currently online */ - current_cpu = (++next_vcpu % mp_ncpus); - channel->target_cpu = current_cpu; - channel->target_vcpu = - hv_vmbus_g_context.hv_vcpu_index[current_cpu]; - if (bootverbose) - printf("VMBUS: Total online cpus %d, assign perf channel %d " - "to vcpu %d, cpu %d\n", mp_ncpus, i, channel->target_vcpu, - current_cpu); -} - -/** * @brief Handler for channel offers from Hyper-V/Azure * * Handler for channel offers from vmbus in parent partition. We ignore @@ -359,12 +296,6 @@ offer = (hv_vmbus_channel_offer_channel*) hdr; - hv_guid *guidType; - hv_guid *guidInstance; - - guidType = &offer->offer.interface_type; - guidInstance = &offer->offer.interface_instance; - // copy offer data copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT); if (copied == NULL) { @@ -411,12 +342,6 @@ offer->connection_id; } - /* - * Bind the channel to a chosen cpu. - */ - vmbus_channel_select_cpu(new_channel, - &offer->offer.interface_type); - memcpy(&new_channel->offer_msg, offer, sizeof(hv_vmbus_channel_offer_channel)); new_channel->monitor_group = (uint8_t) offer->monitor_id / 32; Index: sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c =================================================================== --- sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -279,10 +279,28 @@ return (ENOENT); } + +static int +vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen) +{ + char guidbuf[50]; + struct hv_device *dev_ctx = device_get_ivars(child); + + strlcat(buf, "classid=", buflen); + snprintf_uuid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id); + strlcat(buf, guidbuf, buflen); + + strlcat(buf, " deviceid=", buflen); + snprintf_uuid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id); + strlcat(buf, guidbuf, buflen); + + return (0); +} + struct hv_device* hv_vmbus_child_device_create( - hv_guid type, - hv_guid instance, + struct uuid *type, + struct uuid *instance, hv_vmbus_channel* channel) { hv_device* child_dev; @@ -294,32 +312,18 @@ M_WAITOK | M_ZERO); child_dev->channel = channel; - memcpy(&child_dev->class_id, &type, sizeof(hv_guid)); - memcpy(&child_dev->device_id, &instance, sizeof(hv_guid)); + memcpy(&child_dev->class_id, type, sizeof(struct uuid)); + memcpy(&child_dev->device_id, instance, sizeof(struct uuid)); return (child_dev); } -static void -print_dev_guid(struct hv_device *dev) -{ - int i; - unsigned char guid_name[100]; - for (i = 0; i < 32; i += 2) - sprintf(&guid_name[i], "%02x", dev->class_id.data[i / 2]); - if(bootverbose) - printf("VMBUS: Class ID: %s\n", guid_name); -} - int hv_vmbus_child_device_register(struct hv_device *child_dev) { device_t child; int ret = 0; - print_dev_guid(child_dev); - - child = device_add_child(vmbus_devp, NULL, -1); child_dev->device = child; device_set_ivars(child, child_dev); @@ -328,7 +332,7 @@ ret = device_probe_and_attach(child); mtx_unlock(&Giant); - return (0); + return (ret); } int @@ -714,6 +718,7 @@ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, vmbus_read_ivar), DEVMETHOD(bus_write_ivar, vmbus_write_ivar), + DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str), { 0, 0 } }; Index: sys/dev/hyperv/vmbus/hv_vmbus_priv.h =================================================================== --- sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -90,8 +90,8 @@ typedef struct { uint32_t rel_id; hv_vmbus_channel_state state; - hv_guid interface_type; - hv_guid interface_instance; + struct uuid interface_type; + struct uuid interface_instance; uint32_t monitor_id; uint32_t server_monitor_pending; uint32_t server_monitor_latency; @@ -697,8 +697,8 @@ int hv_vmbus_query_hypervisor_presence(void); struct hv_device* hv_vmbus_child_device_create( - hv_guid device_type, - hv_guid device_instance, + struct uuid *device_type, + struct uuid *device_instance, hv_vmbus_channel *channel); int hv_vmbus_child_device_register(