From f7157cc0c68303388581a3676ba1bf7e63dd96c2 Mon Sep 17 00:00:00 2001 From: sephe Date: Thu, 16 Jun 2016 03:04:16 +0000 Subject: [PATCH] MFC 297142,297143,297176,297177,297178,297221 297142 hyperv: Factor out snprinf_hv_guid() Submitted by: Ju Sun Reviewed by: Dexuan Cui , sephe MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5651 297143 hyperv/vmbus: Implement bus_child_pnpinfo_str method Submitted by: Jun Su Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5669 297176 hyperv/evttimer: Use an independent message slot so that it can work Using the same message slot as the other types of the messages has the side effect that the event timer message could be deferred to the swi threads to run (lacking of trapframe and the original code didn't even handle that, so the event timer was actually broken). As of this commit we use an independent message slot for event timer, so that we could handle all of event timer messages in the interrupt handler directly. Note, the message slot for event timer is still bind to the same interrupt vector as the other types of messages. Submitted by: Jun Su Reviewed by: sephe Discussed with: Jun Su , Dexuan Cui MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5696 297177 hyperv/vmbus: Use taskqueue_fast for non-performance critical messages This gets rid of the per-cpu SWIs. Submitted by: Jun Su Reviewed by: Dexuan Cui , sephe MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5215 297178 hyperv/vmbus: Remove NULL check for taskqueue_create_fast(M_WAITOK) Submitted by: Jun Su Reviewed by: Dexuan Cui , sephe MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D5215 297221 hyperv/vmbus: Create per-cpu fast taskqueue for msg handling Using one taskqueue does not work, since the EOM MSR must be written on the msg's owner CPU. Noticed by: Jun Su Discussed with: Jun Su , Dexuan Cui MFC after: 1 week Sponsored by: Microsoft OSTC git-svn-id: svn://svn.freebsd.org/base/stable/10@301946 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/hyperv/include/hyperv.h | 2 + sys/dev/hyperv/utilities/hv_kvp.c | 29 +---- sys/dev/hyperv/vmbus/hv_et.c | 2 +- sys/dev/hyperv/vmbus/hv_hv.c | 16 ++- sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c | 112 +++++++++++--------- sys/dev/hyperv/vmbus/hv_vmbus_priv.h | 7 +- 6 files changed, 83 insertions(+), 85 deletions(-) diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 0a057c809..26a2bfcb7 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -124,6 +124,8 @@ typedef struct hv_guid { unsigned char data[16]; } __packed hv_guid; +int snprintf_hv_guid(char *, size_t, const hv_guid *); + #define HV_NIC_GUID \ .data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \ 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E} diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index 8517918f6..3012a3f12 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -304,28 +304,11 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, { 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; device_t *devs; int devcnt; @@ -352,17 +335,7 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, /* 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_hv_guid(buf, sizeof(buf), &hv_dev->device_id); sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt])); if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) { diff --git a/sys/dev/hyperv/vmbus/hv_et.c b/sys/dev/hyperv/vmbus/hv_et.c index d96148673..9fb6e2389 100644 --- a/sys/dev/hyperv/vmbus/hv_et.c +++ b/sys/dev/hyperv/vmbus/hv_et.c @@ -60,7 +60,7 @@ hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime) timer_cfg.as_uint64 = 0; timer_cfg.auto_enable = 1; - timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT; + timer_cfg.sintx = HV_VMBUS_TIMER_SINT; periodticks[curcpu] = sbintime2tick(periodtime); if (firsttime == 0) diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c index a7dad3791..74e61bd5e 100644 --- a/sys/dev/hyperv/vmbus/hv_hv.c +++ b/sys/dev/hyperv/vmbus/hv_hv.c @@ -370,6 +370,9 @@ hv_vmbus_synic_init(void *arg) wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT, shared_sint.as_uint64_t); + wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT, + shared_sint.as_uint64_t); + /* Enable the global synic bit */ sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL); sctrl.u.enable = 1; @@ -406,12 +409,23 @@ void hv_vmbus_synic_cleanup(void *arg) shared_sint.u.masked = 1; /* - * Disable the interrupt + * Disable the interrupt 0 */ wrmsr( HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT, shared_sint.as_uint64_t); + shared_sint.as_uint64_t = rdmsr( + HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT); + + shared_sint.u.masked = 1; + + /* + * Disable the interrupt 1 + */ + wrmsr( + HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT, + shared_sint.as_uint64_t); simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP); simp.u.simp_enabled = 0; simp.u.base_simp_gpa = 0; diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c index 2e17e53f8..36f189433 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c +++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include "hv_vmbus_priv.h" #include @@ -75,7 +76,7 @@ static char *vmbus_ids[] = { "VMBUS", NULL }; * the hypervisor. */ static void -vmbus_msg_swintr(void *arg) +vmbus_msg_swintr(void *arg, int pending __unused) { int cpu; void* page_addr; @@ -178,12 +179,15 @@ hv_vmbus_isr(struct trapframe *frame) /* Check if there are actual msgs to be process */ page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu]; - msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT; + msg = (hv_vmbus_message*) page_addr + HV_VMBUS_TIMER_SINT; /* we call eventtimer process the message */ if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) { msg->header.message_type = HV_MESSAGE_TYPE_NONE; + /* call intrrupt handler of event timer */ + hv_et_intr(frame); + /* * Make sure the write to message_type (ie set to * HV_MESSAGE_TYPE_NONE) happens before we read the @@ -204,12 +208,12 @@ hv_vmbus_isr(struct trapframe *frame) */ wrmsr(HV_X64_MSR_EOM, 0); } - hv_et_intr(frame); - return (FILTER_HANDLED); } + msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT; if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) { - swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0); + taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu], + &hv_vmbus_g_context.hv_msg_task[cpu]); } return (FILTER_HANDLED); @@ -287,6 +291,23 @@ vmbus_write_ivar( return (ENOENT); } +static int +vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen) +{ + char guidbuf[40]; + struct hv_device *dev_ctx = device_get_ivars(child); + + strlcat(buf, "classid=", buflen); + snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id); + strlcat(buf, guidbuf, buflen); + + strlcat(buf, " deviceid=", buflen); + snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id); + strlcat(buf, guidbuf, buflen); + + return (0); +} + struct hv_device* hv_vmbus_child_device_create( hv_guid type, @@ -308,15 +329,17 @@ hv_vmbus_child_device_create( return (child_dev); } -static void -print_dev_guid(struct hv_device *dev) +int +snprintf_hv_guid(char *buf, size_t sz, const hv_guid *guid) { - 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 cnt; + const unsigned char *d = guid->data; + + cnt = snprintf(buf, sz, + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6], + d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + return (cnt); } int @@ -325,8 +348,11 @@ hv_vmbus_child_device_register(struct hv_device *child_dev) device_t child; int ret = 0; - print_dev_guid(child_dev); - + if (bootverbose) { + char name[40]; + snprintf_hv_guid(name, sizeof(name), &child_dev->class_id); + printf("VMBUS: Class ID: %s\n", name); + } child = device_add_child(vmbus_devp, NULL, -1); child_dev->device = child; @@ -506,9 +532,6 @@ vmbus_bus_init(void) setup_args.vector = hv_vmbus_g_context.hv_cb_vector; CPU_FOREACH(j) { - hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; - hv_vmbus_g_context.msg_swintr[j] = NULL; - snprintf(buf, sizeof(buf), "cpu%d:hyperv", j); intrcnt_add(buf, &hv_vmbus_intr_cpu[j]); @@ -527,11 +550,6 @@ vmbus_bus_init(void) */ hv_vmbus_g_context.hv_event_queue[j] = taskqueue_create_fast("hyperv event", M_WAITOK, taskqueue_thread_enqueue, &hv_vmbus_g_context.hv_event_queue[j]); - if (hv_vmbus_g_context.hv_event_queue[j] == NULL) { - if (bootverbose) - printf("VMBUS: failed to setup taskqueue\n"); - goto cleanup1; - } taskqueue_start_threads(&hv_vmbus_g_context.hv_event_queue[j], 1, PI_NET, "hvevent%d", j); @@ -541,29 +559,20 @@ vmbus_bus_init(void) taskqueue_drain(hv_vmbus_g_context.hv_event_queue[j], &cpuset_task); /* - * Setup software interrupt thread and handler for msg handling. + * Setup per-cpu tasks and taskqueues to handle msg. */ - ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j], - "hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0, - &hv_vmbus_g_context.msg_swintr[j]); - if (ret) { - if(bootverbose) - printf("VMBUS: failed to setup msg swi for " - "cpu %d\n", j); - goto cleanup1; - } + hv_vmbus_g_context.hv_msg_tq[j] = taskqueue_create_fast( + "hyperv msg", M_WAITOK, taskqueue_thread_enqueue, + &hv_vmbus_g_context.hv_msg_tq[j]); + taskqueue_start_threads(&hv_vmbus_g_context.hv_msg_tq[j], 1, PI_NET, + "hvmsg%d", j); + TASK_INIT(&hv_vmbus_g_context.hv_msg_task[j], 0, + vmbus_msg_swintr, (void *)(long)j); - /* - * Bind the swi thread to the cpu. - */ - ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j], - j); - if (ret) { - if(bootverbose) - printf("VMBUS: failed to bind msg swi thread " - "to cpu %d\n", j); - goto cleanup1; - } + CPU_SETOF(j, &cpu_mask); + TASK_INIT(&cpuset_task, 0, vmbus_cpuset_setthread_task, &cpu_mask); + taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[j], &cpuset_task); + taskqueue_drain(hv_vmbus_g_context.hv_msg_tq[j], &cpuset_task); /* * Prepare the per cpu msg and event pages to be called on each cpu. @@ -603,11 +612,10 @@ vmbus_bus_init(void) * remove swi and vmbus callback vector; */ CPU_FOREACH(j) { - if (hv_vmbus_g_context.hv_event_queue[j] != NULL) + if (hv_vmbus_g_context.hv_event_queue[j] != NULL) { taskqueue_free(hv_vmbus_g_context.hv_event_queue[j]); - if (hv_vmbus_g_context.msg_swintr[j] != NULL) - swi_remove(hv_vmbus_g_context.msg_swintr[j]); - hv_vmbus_g_context.hv_msg_intr_event[j] = NULL; + hv_vmbus_g_context.hv_event_queue[j] = NULL; + } } vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); @@ -672,11 +680,10 @@ vmbus_bus_exit(void) /* remove swi */ CPU_FOREACH(i) { - if (hv_vmbus_g_context.hv_event_queue[i] != NULL) + if (hv_vmbus_g_context.hv_event_queue[i] != NULL) { taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]); - if (hv_vmbus_g_context.msg_swintr[i] != NULL) - swi_remove(hv_vmbus_g_context.msg_swintr[i]); - hv_vmbus_g_context.hv_msg_intr_event[i] = NULL; + hv_vmbus_g_context.hv_event_queue[i] = NULL; + } } vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector); @@ -741,6 +748,7 @@ static device_method_t vmbus_methods[] = { 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 } }; diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h index 86f39908c..5e322567e 100644 --- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h +++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h @@ -181,7 +181,8 @@ enum { HV_VMBUS_EVENT_PORT_ID = 2, HV_VMBUS_MONITOR_CONNECTION_ID = 3, HV_VMBUS_MONITOR_PORT_ID = 3, - HV_VMBUS_MESSAGE_SINT = 2 + HV_VMBUS_MESSAGE_SINT = 2, + HV_VMBUS_TIMER_SINT = 4, }; #define HV_PRESENT_BIT 0x80000000 @@ -204,8 +205,8 @@ typedef struct { * event and msg handling. */ struct taskqueue *hv_event_queue[MAXCPU]; - struct intr_event *hv_msg_intr_event[MAXCPU]; - void *msg_swintr[MAXCPU]; + struct taskqueue *hv_msg_tq[MAXCPU]; + struct task hv_msg_task[MAXCPU]; /* * Host use this vector to intrrupt guest for vmbus channel * event and msg. -- 2.45.0