From owner-svn-src-all@freebsd.org Wed May 18 03:41:38 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 9A214B3F545; Wed, 18 May 2016 03:41:38 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5BC471AC5; Wed, 18 May 2016 03:41:38 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4I3fb3C006928; Wed, 18 May 2016 03:41:37 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4I3fbXx006924; Wed, 18 May 2016 03:41:37 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201605180341.u4I3fbXx006924@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Wed, 18 May 2016 03:41:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r300107 - head/sys/dev/hyperv/vmbus X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 18 May 2016 03:41:38 -0000 Author: sephe Date: Wed May 18 03:41:37 2016 New Revision: 300107 URL: https://svnweb.freebsd.org/changeset/base/300107 Log: hyperv/vmbus: Avoid two unnecessary protocol checks on isr handling path MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6405 Modified: head/sys/dev/hyperv/vmbus/hv_connection.c head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h head/sys/dev/hyperv/vmbus/vmbus_var.h Modified: head/sys/dev/hyperv/vmbus/hv_connection.c ============================================================================== --- head/sys/dev/hyperv/vmbus/hv_connection.c Wed May 18 03:34:02 2016 (r300106) +++ head/sys/dev/hyperv/vmbus/hv_connection.c Wed May 18 03:41:37 2016 (r300107) @@ -289,56 +289,20 @@ hv_vmbus_disconnect(void) { return (ret); } -/** - * Handler for events - */ -void -hv_vmbus_on_events(int cpu) +static __inline void +vmbus_event_flags_proc(unsigned long *event_flags, int flag_cnt) { - unsigned long *intr_flags; - hv_vmbus_synic_event_flags *event; - void *page_addr; - int flag_cnt, f; - - KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: " - "cpu out of range!")); - - page_addr = hv_vmbus_g_context.syn_ic_event_page[cpu]; - event = (hv_vmbus_synic_event_flags *) - page_addr + HV_VMBUS_MESSAGE_SINT; - if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) || - (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) { - flag_cnt = HV_MAX_NUM_CHANNELS_SUPPORTED >> - HV_CHANNEL_ULONG_SHIFT; - /* - * receive size is 1/2 page and divide that by 4 bytes - */ - if (atomic_testandclear_int(&event->flags32[0], 0)) - intr_flags = hv_vmbus_g_connection.recv_interrupt_page; - else - return; - } else { - /* - * On Host with Win8 or above, the event page can be - * checked directly to get the id of the channel - * that has the pending interrupt. - */ - flag_cnt = VMBUS_PCPU_GET(event_flag_cnt, cpu); - intr_flags = event->flagsul; - } + int f; - /* - * Check events - */ - for (f = 0; f < flag_cnt; f++) { + for (f = 0; f < flag_cnt; ++f) { uint32_t rel_id_base; unsigned long flags; int bit; - if (intr_flags[f] == 0) + if (event_flags[f] == 0) continue; - flags = atomic_swap_long(&intr_flags[f], 0); + flags = atomic_swap_long(&event_flags[f], 0); rel_id_base = f << HV_CHANNEL_ULONG_SHIFT; while ((bit = ffsl(flags)) != 0) { @@ -362,6 +326,37 @@ hv_vmbus_on_events(int cpu) } } +void +vmbus_event_proc(struct vmbus_softc *sc, int cpu) +{ + hv_vmbus_synic_event_flags *event; + + event = ((hv_vmbus_synic_event_flags *) + hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT; + + /* + * On Host with Win8 or above, the event page can be checked directly + * to get the id of the channel that has the pending interrupt. + */ + vmbus_event_flags_proc(event->flagsul, + VMBUS_SC_PCPU_GET(sc, event_flag_cnt, cpu)); +} + +void +vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu) +{ + hv_vmbus_synic_event_flags *event; + + event = ((hv_vmbus_synic_event_flags *) + hv_vmbus_g_context.syn_ic_event_page[cpu]) + HV_VMBUS_MESSAGE_SINT; + + if (atomic_testandclear_int(&event->flags32[0], 0)) { + vmbus_event_flags_proc( + hv_vmbus_g_connection.recv_interrupt_page, + HV_MAX_NUM_CHANNELS_SUPPORTED >> HV_CHANNEL_ULONG_SHIFT); + } +} + /** * Send a msg on the vmbus's message connection */ Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c ============================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c Wed May 18 03:34:02 2016 (r300106) +++ head/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c Wed May 18 03:41:37 2016 (r300107) @@ -146,6 +146,7 @@ handled: static inline int hv_vmbus_isr(struct trapframe *frame) { + struct vmbus_softc *sc = vmbus_get_softc(); int cpu; hv_vmbus_message* msg; void* page_addr; @@ -157,8 +158,7 @@ hv_vmbus_isr(struct trapframe *frame) * before checking for messages. This is the way they do it * in Windows when running as a guest in Hyper-V */ - - hv_vmbus_on_events(cpu); + sc->vmbus_event_proc(sc, cpu); /* Check if there are actual msgs to be process */ page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu]; @@ -388,6 +388,7 @@ extern inthand_t IDTVEC(hv_vmbus_callbac static int vmbus_bus_init(void) { + struct vmbus_softc *sc; int i, j, n, ret; char buf[MAXCOMLEN + 1]; cpuset_t cpu_mask; @@ -396,6 +397,7 @@ vmbus_bus_init(void) return (0); vmbus_inited = 1; + sc = vmbus_get_softc(); ret = hv_vmbus_init(); @@ -481,6 +483,12 @@ vmbus_bus_init(void) if (ret != 0) goto cleanup1; + if (hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008 || + hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7) + sc->vmbus_event_proc = vmbus_event_proc_compat; + else + sc->vmbus_event_proc = vmbus_event_proc; + hv_vmbus_request_channel_offers(); vmbus_scan(); @@ -515,6 +523,11 @@ vmbus_bus_init(void) return (ret); } +static void +vmbus_event_proc_dummy(struct vmbus_softc *sc __unused, int cpu __unused) +{ +} + static int vmbus_attach(device_t dev) { @@ -524,6 +537,13 @@ vmbus_attach(device_t dev) vmbus_devp = dev; vmbus_sc = device_get_softc(dev); + /* + * Event processing logic will be configured: + * - After the vmbus protocol version negotiation. + * - Before we request channel offers. + */ + vmbus_sc->vmbus_event_proc = vmbus_event_proc_dummy; + #ifndef EARLY_AP_STARTUP /* * If the system has already booted and thread Modified: head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h ============================================================================== --- head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Wed May 18 03:34:02 2016 (r300106) +++ head/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Wed May 18 03:41:37 2016 (r300107) @@ -753,7 +753,6 @@ int hv_vmbus_connect(void); int hv_vmbus_disconnect(void); int hv_vmbus_post_message(void *buffer, size_t buf_size); int hv_vmbus_set_event(hv_vmbus_channel *channel); -void hv_vmbus_on_events(int cpu); /** * Event Timer interfaces Modified: head/sys/dev/hyperv/vmbus/vmbus_var.h ============================================================================== --- head/sys/dev/hyperv/vmbus/vmbus_var.h Wed May 18 03:34:02 2016 (r300106) +++ head/sys/dev/hyperv/vmbus/vmbus_var.h Wed May 18 03:41:37 2016 (r300107) @@ -36,6 +36,7 @@ struct vmbus_pcpu_data { } __aligned(CACHE_LINE_SIZE); struct vmbus_softc { + void (*vmbus_event_proc)(struct vmbus_softc *, int); struct vmbus_pcpu_data vmbus_pcpu[MAXCPU]; }; @@ -47,11 +48,15 @@ vmbus_get_softc(void) return vmbus_sc; } -#define VMBUS_PCPU_GET(field, cpu) \ - (vmbus_get_softc())->vmbus_pcpu[cpu].field -#define VMBUS_PCPU_PTR(field, cpu) \ - &(vmbus_get_softc())->vmbus_pcpu[cpu].field +#define VMBUS_SC_PCPU_GET(sc, field, cpu) (sc)->vmbus_pcpu[(cpu)].field +#define VMBUS_SC_PCPU_PTR(sc, field, cpu) &(sc)->vmbus_pcpu[(cpu)].field +#define VMBUS_PCPU_GET(field, cpu) \ + VMBUS_SC_PCPU_GET(vmbus_get_softc(), field, (cpu)) +#define VMBUS_PCPU_PTR(field, cpu) \ + VMBUS_SC_PCPU_PTR(vmbus_get_softc(), field, (cpu)) void vmbus_on_channel_open(const struct hv_vmbus_channel *); +void vmbus_event_proc(struct vmbus_softc *, int); +void vmbus_event_proc_compat(struct vmbus_softc *, int); #endif /* !_VMBUS_VAR_H_ */