Date: Fri, 24 Jun 2016 02:30:14 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r302170 - in stable/10/sys: conf dev/hyperv/vmbus dev/hyperv/vmbus/amd64 dev/hyperv/vmbus/i386 modules/hyperv/vmbus Message-ID: <201606240230.u5O2UE3Z064822@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Fri Jun 24 02:30:14 2016 New Revision: 302170 URL: https://svnweb.freebsd.org/changeset/base/302170 Log: MFC 301483,301484,301487,301488,301583,301588 301483 hyperv: Move machine dependent bits into machine dependent files. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6701 301484 hyperv/vmbus: Define type for channel messages. And fix message processing; only channel messages are supported. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6706 301487 hyperv/vmbus: Factor out channel message processing This paves the way for further cleanup. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6707 301488 hyperv/vmbus: Constify channel message MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6708 301583 hyperv/vmbus: Busdma-fy MNF and event flags. MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6744 301588 hyperv/vmbus: Change tx_evtflags type to u_long to match vmbus_evtflags MFC after: 1 week Sponsored by: Microsoft OSTC Differential Revision: https://reviews.freebsd.org/D6745 Added: stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c - copied unchanged from r301483, head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c stable/10/sys/dev/hyperv/vmbus/hyperv_machdep.h - copied unchanged from r301483, head/sys/dev/hyperv/vmbus/hyperv_machdep.h stable/10/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c - copied unchanged from r301483, head/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c Modified: stable/10/sys/conf/files.amd64 stable/10/sys/conf/files.i386 stable/10/sys/dev/hyperv/vmbus/hv_channel.c stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c stable/10/sys/dev/hyperv/vmbus/hv_connection.c stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h stable/10/sys/dev/hyperv/vmbus/hyperv.c stable/10/sys/dev/hyperv/vmbus/vmbus.c stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h stable/10/sys/dev/hyperv/vmbus/vmbus_var.h stable/10/sys/modules/hyperv/vmbus/Makefile Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/conf/files.amd64 ============================================================================== --- stable/10/sys/conf/files.amd64 Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/conf/files.amd64 Fri Jun 24 02:30:14 2016 (r302170) @@ -279,6 +279,7 @@ dev/hyperv/vmbus/hyperv.c optional hy dev/hyperv/vmbus/hyperv_busdma.c optional hyperv dev/hyperv/vmbus/vmbus.c optional hyperv dev/hyperv/vmbus/vmbus_et.c optional hyperv +dev/hyperv/vmbus/amd64/hyperv_machdep.c optional hyperv dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv dev/kbd/kbd.c optional atkbd | sc | ukbd | vt dev/lindev/full.c optional lindev Modified: stable/10/sys/conf/files.i386 ============================================================================== --- stable/10/sys/conf/files.i386 Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/conf/files.i386 Fri Jun 24 02:30:14 2016 (r302170) @@ -255,6 +255,7 @@ dev/hyperv/vmbus/hyperv.c optional hy dev/hyperv/vmbus/hyperv_busdma.c optional hyperv dev/hyperv/vmbus/vmbus.c optional hyperv dev/hyperv/vmbus/vmbus_et.c optional hyperv +dev/hyperv/vmbus/i386/hyperv_machdep.c optional hyperv dev/hyperv/vmbus/i386/vmbus_vector.S optional hyperv dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis Copied: stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c (from r301483, head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c Fri Jun 24 02:30:14 2016 (r302170, copy of r301483, head/sys/dev/hyperv/vmbus/amd64/hyperv_machdep.c) @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <dev/hyperv/vmbus/hyperv_machdep.h> + +uint64_t +hypercall_md(volatile void *hc_addr, uint64_t in_val, + uint64_t in_paddr, uint64_t out_paddr) +{ + uint64_t status; + + __asm__ __volatile__ ("mov %0, %%r8" : : "r" (out_paddr): "r8"); + __asm__ __volatile__ ("call *%3" : "=a" (status) : + "c" (in_val), "d" (in_paddr), "m" (hc_addr)); + return (status); +} Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel.c Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel.c Fri Jun 24 02:30:14 2016 (r302170) @@ -37,12 +37,16 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/sysctl.h> + +#include <machine/atomic.h> #include <machine/bus.h> + #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> #include <dev/hyperv/vmbus/hv_vmbus_priv.h> +#include <dev/hyperv/vmbus/vmbus_reg.h> #include <dev/hyperv/vmbus/vmbus_var.h> static int vmbus_channel_create_gpadl_header( @@ -62,17 +66,16 @@ static void VmbusProcessChannelEvent(voi static void vmbus_channel_set_event(hv_vmbus_channel *channel) { - hv_vmbus_monitor_page *monitor_page; - if (channel->offer_msg.monitor_allocated) { - /* Each uint32_t represents 32 channels */ - synch_set_bit((channel->offer_msg.child_rel_id & 31), - ((uint32_t *)hv_vmbus_g_connection.send_interrupt_page - + ((channel->offer_msg.child_rel_id >> 5)))); - - monitor_page = (hv_vmbus_monitor_page *) - hv_vmbus_g_connection.monitor_page_2; + struct vmbus_softc *sc = vmbus_get_softc(); + hv_vmbus_monitor_page *monitor_page; + uint32_t chanid = channel->offer_msg.child_rel_id; + + atomic_set_long( + &sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT], + 1UL << (chanid & VMBUS_EVTFLAG_MASK)); + monitor_page = sc->vmbus_mnf2; synch_set_bit(channel->monitor_bit, (uint32_t *)&monitor_page-> trigger_group[channel->monitor_group].u.pending); Modified: stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/hv_channel_mgmt.c Fri Jun 24 02:30:14 2016 (r302170) @@ -43,20 +43,34 @@ __FBSDID("$FreeBSD$"); * Internal functions */ -static void vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_offer_internal(void* context); -static void vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_offer_rescind_internal(void* context); -static void vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr); -static void vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr); +typedef void (*vmbus_msg_handler)(const hv_vmbus_channel_msg_header *msg); + +typedef struct hv_vmbus_channel_msg_table_entry { + hv_vmbus_channel_msg_type messageType; + vmbus_msg_handler messageHandler; +} hv_vmbus_channel_msg_table_entry; + +static void vmbus_channel_on_offer_internal(void *context); +static void vmbus_channel_on_offer_rescind_internal(void *context); + +static void vmbus_channel_on_offer(const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_open_result( + const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_offer_rescind( + const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_gpadl_created( + const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_gpadl_torndown( + const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_offers_delivered( + const hv_vmbus_channel_msg_header *hdr); +static void vmbus_channel_on_version_response( + const hv_vmbus_channel_msg_header *hdr); /** * Channel message dispatch table */ -hv_vmbus_channel_msg_table_entry +static const hv_vmbus_channel_msg_table_entry g_channel_message_table[HV_CHANNEL_MESSAGE_COUNT] = { { HV_CHANNEL_MESSAGE_INVALID, NULL }, @@ -387,12 +401,12 @@ vmbus_channel_select_defcpu(struct hv_vm * object to process the offer synchronously */ static void -vmbus_channel_on_offer(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_offer(const hv_vmbus_channel_msg_header *hdr) { - hv_vmbus_channel_offer_channel* offer; - hv_vmbus_channel_offer_channel* copied; + const hv_vmbus_channel_offer_channel *offer; + hv_vmbus_channel_offer_channel *copied; - offer = (hv_vmbus_channel_offer_channel*) hdr; + offer = (const hv_vmbus_channel_offer_channel *)hdr; // copy offer data copied = malloc(sizeof(*copied), M_DEVBUF, M_NOWAIT); @@ -465,12 +479,12 @@ vmbus_channel_on_offer_internal(void* co * synchronously */ static void -vmbus_channel_on_offer_rescind(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_offer_rescind(const hv_vmbus_channel_msg_header *hdr) { - hv_vmbus_channel_rescind_offer* rescind; + const hv_vmbus_channel_rescind_offer *rescind; hv_vmbus_channel* channel; - rescind = (hv_vmbus_channel_rescind_offer*) hdr; + rescind = (const hv_vmbus_channel_rescind_offer *)hdr; channel = hv_vmbus_g_connection.channels[rescind->child_rel_id]; if (channel == NULL) @@ -497,7 +511,8 @@ vmbus_channel_on_offer_rescind_internal( * @brief Invoked when all offers have been delivered. */ static void -vmbus_channel_on_offers_delivered(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_offers_delivered( + const hv_vmbus_channel_msg_header *hdr __unused) { mtx_lock(&vmbus_chwait_lock); @@ -514,14 +529,14 @@ vmbus_channel_on_offers_delivered(hv_vmb * response and signal the requesting thread. */ static void -vmbus_channel_on_open_result(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_open_result(const hv_vmbus_channel_msg_header *hdr) { - hv_vmbus_channel_open_result* result; + const hv_vmbus_channel_open_result *result; hv_vmbus_channel_msg_info* msg_info; hv_vmbus_channel_msg_header* requestHeader; hv_vmbus_channel_open_channel* openMsg; - result = (hv_vmbus_channel_open_result*) hdr; + result = (const hv_vmbus_channel_open_result *)hdr; /* * Find the open msg, copy the result and signal/unblock the wait event @@ -556,14 +571,14 @@ vmbus_channel_on_open_result(hv_vmbus_ch * response and signal the requesting thread. */ static void -vmbus_channel_on_gpadl_created(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_gpadl_created(const hv_vmbus_channel_msg_header *hdr) { - hv_vmbus_channel_gpadl_created* gpadl_created; + const hv_vmbus_channel_gpadl_created *gpadl_created; hv_vmbus_channel_msg_info* msg_info; hv_vmbus_channel_msg_header* request_header; hv_vmbus_channel_gpadl_header* gpadl_header; - gpadl_created = (hv_vmbus_channel_gpadl_created*) hdr; + gpadl_created = (const hv_vmbus_channel_gpadl_created *)hdr; /* Find the establish msg, copy the result and signal/unblock * the wait event @@ -598,14 +613,14 @@ vmbus_channel_on_gpadl_created(hv_vmbus_ * response and signal the requesting thread */ static void -vmbus_channel_on_gpadl_torndown(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_gpadl_torndown(const hv_vmbus_channel_msg_header *hdr) { - hv_vmbus_channel_gpadl_torndown* gpadl_torndown; + const hv_vmbus_channel_gpadl_torndown *gpadl_torndown; hv_vmbus_channel_msg_info* msg_info; hv_vmbus_channel_msg_header* requestHeader; hv_vmbus_channel_gpadl_teardown* gpadlTeardown; - gpadl_torndown = (hv_vmbus_channel_gpadl_torndown*)hdr; + gpadl_torndown = (const hv_vmbus_channel_gpadl_torndown *)hdr; /* * Find the open msg, copy the result and signal/unblock the @@ -643,14 +658,14 @@ vmbus_channel_on_gpadl_torndown(hv_vmbus * response and signal the requesting thread. */ static void -vmbus_channel_on_version_response(hv_vmbus_channel_msg_header* hdr) +vmbus_channel_on_version_response(const hv_vmbus_channel_msg_header *hdr) { hv_vmbus_channel_msg_info* msg_info; hv_vmbus_channel_msg_header* requestHeader; hv_vmbus_channel_initiate_contact* initiate; - hv_vmbus_channel_version_response* versionResponse; + const hv_vmbus_channel_version_response *versionResponse; - versionResponse = (hv_vmbus_channel_version_response*)hdr; + versionResponse = (const hv_vmbus_channel_version_response *)hdr; mtx_lock(&hv_vmbus_g_connection.channel_msg_lock); TAILQ_FOREACH(msg_info, &hv_vmbus_g_connection.channel_msg_anchor, @@ -834,3 +849,24 @@ vmbus_rel_subchan(struct hv_vmbus_channe free(subchan, M_TEMP); } + +void +vmbus_chan_msgproc(struct vmbus_softc *sc, const struct vmbus_message *msg) +{ + const hv_vmbus_channel_msg_table_entry *entry; + const hv_vmbus_channel_msg_header *hdr; + hv_vmbus_channel_msg_type msg_type; + + hdr = (const hv_vmbus_channel_msg_header *)msg->msg_data; + msg_type = hdr->message_type; + + if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) { + device_printf(sc->vmbus_dev, "unknown message type 0x%x\n", + msg_type); + return; + } + + entry = &g_channel_message_table[msg_type]; + if (entry->messageHandler) + entry->messageHandler(hdr); +} Modified: stable/10/sys/dev/hyperv/vmbus/hv_connection.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_connection.c Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/hv_connection.c Fri Jun 24 02:30:14 2016 (r302170) @@ -77,8 +77,8 @@ hv_vmbus_get_next_version(uint32_t curre * Negotiate the highest supported hypervisor version. */ static int -hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info, - uint32_t version) +hv_vmbus_negotiate_version(struct vmbus_softc *sc, + hv_vmbus_channel_msg_info *msg_info, uint32_t version) { int ret = 0; hv_vmbus_channel_initiate_contact *msg; @@ -89,14 +89,9 @@ hv_vmbus_negotiate_version(hv_vmbus_chan msg->header.message_type = HV_CHANNEL_MESSAGE_INITIATED_CONTACT; msg->vmbus_version_requested = version; - msg->interrupt_page = hv_get_phys_addr( - hv_vmbus_g_connection.interrupt_page); - - msg->monitor_page_1 = hv_get_phys_addr( - hv_vmbus_g_connection.monitor_page_1); - - msg->monitor_page_2 = hv_get_phys_addr( - hv_vmbus_g_connection.monitor_page_2); + msg->interrupt_page = sc->vmbus_evtflags_dma.hv_paddr; + msg->monitor_page_1 = sc->vmbus_mnf1_dma.hv_paddr; + msg->monitor_page_2 = sc->vmbus_mnf2_dma.hv_paddr; /** * Add to list before we send the request since we may receive the @@ -153,7 +148,7 @@ hv_vmbus_negotiate_version(hv_vmbus_chan * Send a connect request on the partition service connection */ int -hv_vmbus_connect(void) +hv_vmbus_connect(struct vmbus_softc *sc) { int ret = 0; uint32_t version; @@ -179,34 +174,6 @@ hv_vmbus_connect(void) mtx_init(&hv_vmbus_g_connection.channel_lock, "vmbus channel", NULL, MTX_DEF); - /** - * Setup the vmbus event connection for channel interrupt abstraction - * stuff - */ - hv_vmbus_g_connection.interrupt_page = malloc( - PAGE_SIZE, M_DEVBUF, - M_WAITOK | M_ZERO); - - hv_vmbus_g_connection.recv_interrupt_page = - hv_vmbus_g_connection.interrupt_page; - - hv_vmbus_g_connection.send_interrupt_page = - ((uint8_t *) hv_vmbus_g_connection.interrupt_page + - (PAGE_SIZE >> 1)); - - /** - * Set up the monitor notification facility. The 1st page for - * parent->child and the 2nd page for child->parent - */ - hv_vmbus_g_connection.monitor_page_1 = malloc( - PAGE_SIZE, - M_DEVBUF, - M_WAITOK | M_ZERO); - hv_vmbus_g_connection.monitor_page_2 = malloc( - PAGE_SIZE, - M_DEVBUF, - M_WAITOK | M_ZERO); - msg_info = (hv_vmbus_channel_msg_info*) malloc(sizeof(hv_vmbus_channel_msg_info) + sizeof(hv_vmbus_channel_initiate_contact), @@ -220,7 +187,7 @@ hv_vmbus_connect(void) version = HV_VMBUS_VERSION_CURRENT; do { - ret = hv_vmbus_negotiate_version(msg_info, version); + ret = hv_vmbus_negotiate_version(sc, msg_info, version); if (ret == EWOULDBLOCK) { /* * We timed out. @@ -254,14 +221,6 @@ hv_vmbus_connect(void) mtx_destroy(&hv_vmbus_g_connection.channel_lock); mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); - if (hv_vmbus_g_connection.interrupt_page != NULL) { - free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF); - hv_vmbus_g_connection.interrupt_page = NULL; - } - - free(hv_vmbus_g_connection.monitor_page_1, M_DEVBUF); - free(hv_vmbus_g_connection.monitor_page_2, M_DEVBUF); - if (msg_info) { sema_destroy(&msg_info->wait_sema); free(msg_info, M_DEVBUF); @@ -284,8 +243,6 @@ hv_vmbus_disconnect(void) ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload)); - free(hv_vmbus_g_connection.interrupt_page, M_DEVBUF); - mtx_destroy(&hv_vmbus_g_connection.channel_msg_lock); free(hv_vmbus_g_connection.channels, M_DEVBUF); @@ -346,14 +303,13 @@ vmbus_event_proc(struct vmbus_softc *sc, } void -vmbus_event_proc_compat(struct vmbus_softc *sc __unused, int cpu) +vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) { struct vmbus_evtflags *eventf; eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) { - vmbus_event_flags_proc( - hv_vmbus_g_connection.recv_interrupt_page, + vmbus_event_flags_proc(sc->vmbus_rx_evtflags, VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT); } } @@ -376,8 +332,8 @@ int hv_vmbus_post_message(void *buffer, * insufficient resources. 20 times should suffice in practice. */ for (retries = 0; retries < 20; retries++) { - ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, - bufferLen); + ret = hv_vmbus_post_msg_via_msg_ipc(connId, + VMBUS_MSGTYPE_CHANNEL, buffer, bufferLen); if (ret == HV_STATUS_SUCCESS) return (0); @@ -398,14 +354,12 @@ int hv_vmbus_post_message(void *buffer, int hv_vmbus_set_event(hv_vmbus_channel *channel) { + struct vmbus_softc *sc = vmbus_get_softc(); int ret = 0; - uint32_t child_rel_id = channel->offer_msg.child_rel_id; - - /* Each uint32_t represents 32 channels */ + uint32_t chanid = channel->offer_msg.child_rel_id; - synch_set_bit(child_rel_id & 31, - (((uint32_t *)hv_vmbus_g_connection.send_interrupt_page - + (child_rel_id >> 5)))); + atomic_set_long(&sc->vmbus_tx_evtflags[chanid >> VMBUS_EVTFLAG_SHIFT], + 1UL << (chanid & VMBUS_EVTFLAG_MASK)); ret = hv_vmbus_signal_event(channel->signal_event_param); return (ret); Modified: stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/hv_vmbus_priv.h Fri Jun 24 02:30:14 2016 (r302170) @@ -244,25 +244,7 @@ typedef enum { typedef struct { hv_vmbus_connect_state connect_state; uint32_t next_gpadl_handle; - /** - * Represents channel interrupts. Each bit position - * represents a channel. - * When a channel sends an interrupt via VMBUS, it - * finds its bit in the send_interrupt_page, set it and - * calls Hv to generate a port event. The other end - * receives the port event and parse the - * recv_interrupt_page to see which bit is set - */ - void *interrupt_page; - void *send_interrupt_page; - void *recv_interrupt_page; - /* - * 2 pages - 1st page for parent->child - * notification and 2nd is child->parent - * notification - */ - void *monitor_page_1; - void *monitor_page_2; + TAILQ_HEAD(, hv_vmbus_channel_msg_info) channel_msg_anchor; struct mtx channel_msg_lock; /** @@ -364,16 +346,6 @@ typedef enum { extern hv_vmbus_connection hv_vmbus_g_connection; -typedef void (*vmbus_msg_handler)(hv_vmbus_channel_msg_header *msg); - -typedef struct hv_vmbus_channel_msg_table_entry { - hv_vmbus_channel_msg_type messageType; - - vmbus_msg_handler messageHandler; -} hv_vmbus_channel_msg_table_entry; - -extern hv_vmbus_channel_msg_table_entry g_channel_message_table[]; - /* * Private, VM Bus functions */ @@ -450,7 +422,8 @@ int hv_vmbus_child_device_unregister( /** * Connection interfaces */ -int hv_vmbus_connect(void); +struct vmbus_softc; +int hv_vmbus_connect(struct vmbus_softc *); 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); Modified: stable/10/sys/dev/hyperv/vmbus/hyperv.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/hyperv.c Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/hyperv.c Fri Jun 24 02:30:14 2016 (r302170) @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <dev/hyperv/include/hyperv_busdma.h> #include <dev/hyperv/vmbus/hv_vmbus_priv.h> +#include <dev/hyperv/vmbus/hyperv_machdep.h> #include <dev/hyperv/vmbus/hyperv_reg.h> #include <dev/hyperv/vmbus/hyperv_var.h> #include <dev/hyperv/vmbus/vmbus_var.h> @@ -104,40 +105,17 @@ hyperv_get_timecount(struct timecounter * @brief Invoke the specified hypercall */ static uint64_t -hv_vmbus_do_hypercall(uint64_t control, void* input, void* output) +hv_vmbus_do_hypercall(uint64_t value, void *input, void *output) { -#ifdef __x86_64__ - uint64_t hv_status = 0; - uint64_t input_address = (input) ? hv_get_phys_addr(input) : 0; - uint64_t output_address = (output) ? hv_get_phys_addr(output) : 0; - volatile void *hypercall_page = hypercall_context.hc_addr; - - __asm__ __volatile__ ("mov %0, %%r8" : : "r" (output_address): "r8"); - __asm__ __volatile__ ("call *%3" : "=a"(hv_status): - "c" (control), "d" (input_address), - "m" (hypercall_page)); - return (hv_status); -#else - uint32_t control_high = control >> 32; - uint32_t control_low = control & 0xFFFFFFFF; - uint32_t hv_status_high = 1; - uint32_t hv_status_low = 1; - uint64_t input_address = (input) ? hv_get_phys_addr(input) : 0; - uint32_t input_address_high = input_address >> 32; - uint32_t input_address_low = input_address & 0xFFFFFFFF; - uint64_t output_address = (output) ? hv_get_phys_addr(output) : 0; - uint32_t output_address_high = output_address >> 32; - uint32_t output_address_low = output_address & 0xFFFFFFFF; - volatile void *hypercall_page = hypercall_context.hc_addr; - - __asm__ __volatile__ ("call *%8" : "=d"(hv_status_high), - "=a"(hv_status_low) : "d" (control_high), - "a" (control_low), "b" (input_address_high), - "c" (input_address_low), - "D"(output_address_high), - "S"(output_address_low), "m" (hypercall_page)); - return (hv_status_low | ((uint64_t)hv_status_high << 32)); -#endif /* __x86_64__ */ + uint64_t in_paddr = 0, out_paddr = 0; + + if (input != NULL) + in_paddr = hv_get_phys_addr(input); + if (output != NULL) + out_paddr = hv_get_phys_addr(output); + + return hypercall_md(hypercall_context.hc_addr, value, + in_paddr, out_paddr); } /** Copied: stable/10/sys/dev/hyperv/vmbus/hyperv_machdep.h (from r301483, head/sys/dev/hyperv/vmbus/hyperv_machdep.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/sys/dev/hyperv/vmbus/hyperv_machdep.h Fri Jun 24 02:30:14 2016 (r302170, copy of r301483, head/sys/dev/hyperv/vmbus/hyperv_machdep.h) @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _HYPERV_MACHDEP_H_ +#define _HYPERV_MACHDEP_H_ + +#include <sys/param.h> + +uint64_t hypercall_md(volatile void *hc_addr, uint64_t in_val, + uint64_t in_paddr, uint64_t out_paddr); + +#endif /* !_HYPERV_MACHDEP_H_ */ Copied: stable/10/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c (from r301483, head/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ stable/10/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c Fri Jun 24 02:30:14 2016 (r302170, copy of r301483, head/sys/dev/hyperv/vmbus/i386/hyperv_machdep.c) @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2016 Microsoft Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <dev/hyperv/vmbus/hyperv_machdep.h> + +uint64_t +hypercall_md(volatile void *hc_addr, uint64_t in_val, + uint64_t in_paddr, uint64_t out_paddr) +{ + uint32_t in_val_hi = in_val >> 32; + uint32_t in_val_lo = in_val & 0xFFFFFFFF; + uint32_t status_hi, status_lo; + uint32_t in_paddr_hi = in_paddr >> 32; + uint32_t in_paddr_lo = in_paddr & 0xFFFFFFFF; + uint32_t out_paddr_hi = out_paddr >> 32; + uint32_t out_paddr_lo = out_paddr & 0xFFFFFFFF; + + __asm__ __volatile__ ("call *%8" : "=d"(status_hi), "=a"(status_lo) : + "d" (in_val_hi), "a" (in_val_lo), + "b" (in_paddr_hi), "c" (in_paddr_lo), + "D"(out_paddr_hi), "S"(out_paddr_lo), + "m" (hc_addr)); + return (status_lo | ((uint64_t)status_hi << 32)); +} Modified: stable/10/sys/dev/hyperv/vmbus/vmbus.c ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus.c Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/vmbus.c Fri Jun 24 02:30:14 2016 (r302170) @@ -81,27 +81,15 @@ vmbus_msg_task(void *xsc, int pending __ msg = VMBUS_PCPU_GET(sc, message, curcpu) + VMBUS_SINT_MESSAGE; for (;;) { - const hv_vmbus_channel_msg_table_entry *entry; - hv_vmbus_channel_msg_header *hdr; - hv_vmbus_channel_msg_type msg_type; - - if (msg->msg_type == VMBUS_MSGTYPE_NONE) - break; /* no message */ - - /* XXX: update messageHandler interface */ - hdr = __DEVOLATILE(hv_vmbus_channel_msg_header *, - msg->msg_data); - msg_type = hdr->message_type; - - if (msg_type >= HV_CHANNEL_MESSAGE_COUNT) { - printf("VMBUS: unknown message type = %d\n", msg_type); - goto handled; + if (msg->msg_type == VMBUS_MSGTYPE_NONE) { + /* No message */ + break; + } else if (msg->msg_type == VMBUS_MSGTYPE_CHANNEL) { + /* Channel message */ + vmbus_chan_msgproc(sc, + __DEVOLATILE(const struct vmbus_message *, msg)); } - entry = &g_channel_message_table[msg_type]; - if (entry->messageHandler) - entry->messageHandler(hdr); -handled: msg->msg_type = VMBUS_MSGTYPE_NONE; /* * Make sure the write to msg_type (i.e. set to @@ -321,30 +309,50 @@ vmbus_synic_teardown(void *arg) static int vmbus_dma_alloc(struct vmbus_softc *sc) { + bus_dma_tag_t parent_dtag; + uint8_t *evtflags; int cpu; + parent_dtag = bus_get_dma_tag(sc->vmbus_dev); CPU_FOREACH(cpu) { void *ptr; /* * Per-cpu messages and event flags. */ - ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev), - PAGE_SIZE, 0, PAGE_SIZE, - VMBUS_PCPU_PTR(sc, message_dma, cpu), + ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, + PAGE_SIZE, VMBUS_PCPU_PTR(sc, message_dma, cpu), BUS_DMA_WAITOK | BUS_DMA_ZERO); if (ptr == NULL) return ENOMEM; VMBUS_PCPU_GET(sc, message, cpu) = ptr; - ptr = hyperv_dmamem_alloc(bus_get_dma_tag(sc->vmbus_dev), - PAGE_SIZE, 0, PAGE_SIZE, - VMBUS_PCPU_PTR(sc, event_flags_dma, cpu), + ptr = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, + PAGE_SIZE, VMBUS_PCPU_PTR(sc, event_flags_dma, cpu), BUS_DMA_WAITOK | BUS_DMA_ZERO); if (ptr == NULL) return ENOMEM; VMBUS_PCPU_GET(sc, event_flags, cpu) = ptr; } + + evtflags = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, + PAGE_SIZE, &sc->vmbus_evtflags_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (evtflags == NULL) + return ENOMEM; + sc->vmbus_rx_evtflags = (u_long *)evtflags; + sc->vmbus_tx_evtflags = (u_long *)(evtflags + (PAGE_SIZE / 2)); + sc->vmbus_evtflags = evtflags; + + sc->vmbus_mnf1 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, + PAGE_SIZE, &sc->vmbus_mnf1_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (sc->vmbus_mnf1 == NULL) + return ENOMEM; + + sc->vmbus_mnf2 = hyperv_dmamem_alloc(parent_dtag, PAGE_SIZE, 0, + PAGE_SIZE, &sc->vmbus_mnf2_dma, BUS_DMA_WAITOK | BUS_DMA_ZERO); + if (sc->vmbus_mnf2 == NULL) + return ENOMEM; + return 0; } @@ -353,6 +361,21 @@ vmbus_dma_free(struct vmbus_softc *sc) { int cpu; + if (sc->vmbus_evtflags != NULL) { + hyperv_dmamem_free(&sc->vmbus_evtflags_dma, sc->vmbus_evtflags); + sc->vmbus_evtflags = NULL; + sc->vmbus_rx_evtflags = NULL; + sc->vmbus_tx_evtflags = NULL; + } + if (sc->vmbus_mnf1 != NULL) { + hyperv_dmamem_free(&sc->vmbus_mnf1_dma, sc->vmbus_mnf1); + sc->vmbus_mnf1 = NULL; + } + if (sc->vmbus_mnf2 != NULL) { + hyperv_dmamem_free(&sc->vmbus_mnf2_dma, sc->vmbus_mnf2); + sc->vmbus_mnf2 = NULL; + } + CPU_FOREACH(cpu) { if (VMBUS_PCPU_GET(sc, message, cpu) != NULL) { hyperv_dmamem_free( @@ -701,8 +724,7 @@ vmbus_bus_init(void) /* * Connect to VMBus in the root partition */ - ret = hv_vmbus_connect(); - + ret = hv_vmbus_connect(sc); if (ret != 0) goto cleanup; Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_reg.h Fri Jun 24 02:30:14 2016 (r302170) @@ -49,6 +49,7 @@ struct vmbus_message { CTASSERT(sizeof(struct vmbus_message) == VMBUS_MSG_SIZE); #define VMBUS_MSGTYPE_NONE 0 +#define VMBUS_MSGTYPE_CHANNEL 1 #define VMBUS_MSGTYPE_TIMER_EXPIRED 0x80000010 #define VMBUS_MSGFLAG_PENDING 0x01 @@ -65,6 +66,7 @@ CTASSERT(sizeof(struct vmbus_message) == #define VMBUS_EVTFLAG_SHIFT 5 #endif #define VMBUS_EVTFLAG_LEN (1 << VMBUS_EVTFLAG_SHIFT) +#define VMBUS_EVTFLAG_MASK (VMBUS_EVTFLAG_LEN - 1) #define VMBUS_EVTFLAGS_SIZE 256 struct vmbus_evtflags { Modified: stable/10/sys/dev/hyperv/vmbus/vmbus_var.h ============================================================================== --- stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/dev/hyperv/vmbus/vmbus_var.h Fri Jun 24 02:30:14 2016 (r302170) @@ -50,7 +50,7 @@ struct vmbus_pcpu_data { struct vmbus_message *message; /* shared messages */ uint32_t vcpuid; /* virtual cpuid */ int event_flags_cnt;/* # of event flags */ - struct vmbus_evtflags *event_flags; /* shared event flags */ + struct vmbus_evtflags *event_flags; /* event flags from host */ /* Rarely used fields */ struct hyperv_dma message_dma; /* busdma glue */ @@ -62,12 +62,26 @@ struct vmbus_pcpu_data { struct vmbus_softc { void (*vmbus_event_proc)(struct vmbus_softc *, int); + u_long *vmbus_tx_evtflags; + /* event flags to host */ + void *vmbus_mnf2; /* monitored by host */ + + u_long *vmbus_rx_evtflags; + /* compat evtflgs from host */ struct vmbus_pcpu_data vmbus_pcpu[MAXCPU]; /* Rarely used fields */ device_t vmbus_dev; int vmbus_idtvec; uint32_t vmbus_flags; /* see VMBUS_FLAG_ */ + + /* Shared memory for vmbus_{rx,tx}_evtflags */ + void *vmbus_evtflags; + struct hyperv_dma vmbus_evtflags_dma; + + void *vmbus_mnf1; /* monitored by VM, unused */ + struct hyperv_dma vmbus_mnf1_dma; + struct hyperv_dma vmbus_mnf2_dma; }; #define VMBUS_FLAG_ATTACHED 0x0001 /* vmbus was attached */ @@ -92,6 +106,7 @@ vmbus_get_device(void) struct hv_vmbus_channel; struct trapframe; +struct vmbus_message; void vmbus_on_channel_open(const struct hv_vmbus_channel *); void vmbus_event_proc(struct vmbus_softc *, int); @@ -100,4 +115,6 @@ void vmbus_handle_intr(struct trapframe void vmbus_et_intr(struct trapframe *); +void vmbus_chan_msgproc(struct vmbus_softc *, const struct vmbus_message *); + #endif /* !_VMBUS_VAR_H_ */ Modified: stable/10/sys/modules/hyperv/vmbus/Makefile ============================================================================== --- stable/10/sys/modules/hyperv/vmbus/Makefile Fri Jun 24 02:28:24 2016 (r302169) +++ stable/10/sys/modules/hyperv/vmbus/Makefile Fri Jun 24 02:30:14 2016 (r302170) @@ -10,6 +10,7 @@ SRCS= hv_channel.c \ hv_ring_buffer.c \ hyperv.c \ hyperv_busdma.c \ + hyperv_machdep.c \ vmbus.c \ vmbus_et.c SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606240230.u5O2UE3Z064822>