From owner-svn-src-all@freebsd.org Thu Jan 5 05:46:08 2017 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 15622C9F6E3; Thu, 5 Jan 2017 05:46:08 +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 CB86A111E; Thu, 5 Jan 2017 05:46:07 +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 v055k7nP007123; Thu, 5 Jan 2017 05:46:07 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v055k6nR007118; Thu, 5 Jan 2017 05:46:06 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201701050546.v055k6nR007118@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Thu, 5 Jan 2017 05:46:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r311367 - in stable/11/sys/dev/hyperv: include vmbus X-SVN-Group: stable-11 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.23 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: Thu, 05 Jan 2017 05:46:08 -0000 Author: sephe Date: Thu Jan 5 05:46:06 2017 New Revision: 311367 URL: https://svnweb.freebsd.org/changeset/base/311367 Log: MFC 309240,309242,309244,309245,309670 309240 hyperv/vmbus: Add result polling support for xact API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8633 309242 hyperv/vmbus: Add result polling support for message Hypercall API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8634 309244 hyperv/vmbus: Add exec cancel support for message Hypercall API. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8635 309245 hyperv/vmbus: Use poll/cancel APIs to wait for the CHOPEN response. Since hypervisor does not respond CHOPEN to a revoked channel. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8636 309670 hyperv/vmbus: Use pause if possible. This makes booting on Hyper-V w/ small # of vCPUs work properly. Reported by: Hongxiong Xian , Hongjiang Zhang Sponsored by: Microsoft Modified: stable/11/sys/dev/hyperv/include/vmbus_xact.h stable/11/sys/dev/hyperv/vmbus/vmbus.c stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c stable/11/sys/dev/hyperv/vmbus/vmbus_var.h stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/hyperv/include/vmbus_xact.h ============================================================================== --- stable/11/sys/dev/hyperv/include/vmbus_xact.h Thu Jan 5 05:41:33 2017 (r311366) +++ stable/11/sys/dev/hyperv/include/vmbus_xact.h Thu Jan 5 05:46:06 2017 (r311367) @@ -55,6 +55,8 @@ const void *vmbus_xact_wait(struct vmbu size_t *resp_len); const void *vmbus_xact_busywait(struct vmbus_xact *xact, size_t *resp_len); +const void *vmbus_xact_poll(struct vmbus_xact *xact, + size_t *resp_len); void vmbus_xact_wakeup(struct vmbus_xact *xact, const void *data, size_t dlen); void vmbus_xact_ctx_wakeup(struct vmbus_xact_ctx *ctx, Modified: stable/11/sys/dev/hyperv/vmbus/vmbus.c ============================================================================== --- stable/11/sys/dev/hyperv/vmbus/vmbus.c Thu Jan 5 05:41:33 2017 (r311366) +++ stable/11/sys/dev/hyperv/vmbus/vmbus.c Thu Jan 5 05:46:06 2017 (r311367) @@ -310,6 +310,13 @@ vmbus_msghc_exec(struct vmbus_softc *sc return error; } +void +vmbus_msghc_exec_cancel(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) +{ + + vmbus_xact_deactivate(mh->mh_xact); +} + const struct vmbus_message * vmbus_msghc_wait_result(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) { @@ -318,6 +325,14 @@ vmbus_msghc_wait_result(struct vmbus_sof return (vmbus_xact_wait(mh->mh_xact, &resp_len)); } +const struct vmbus_message * +vmbus_msghc_poll_result(struct vmbus_softc *sc __unused, struct vmbus_msghc *mh) +{ + size_t resp_len; + + return (vmbus_xact_poll(mh->mh_xact, &resp_len)); +} + void vmbus_msghc_wakeup(struct vmbus_softc *sc, const struct vmbus_message *msg) { Modified: stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c ============================================================================== --- stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c Thu Jan 5 05:41:33 2017 (r311366) +++ stable/11/sys/dev/hyperv/vmbus/vmbus_chan.c Thu Jan 5 05:46:06 2017 (r311367) @@ -67,7 +67,7 @@ static void vmbus_chan_set_chmap(struc static void vmbus_chan_clear_chmap(struct vmbus_channel *); static void vmbus_chan_detach(struct vmbus_channel *); static bool vmbus_chan_wait_revoke( - const struct vmbus_channel *); + const struct vmbus_channel *, bool); static void vmbus_chan_ins_prilist(struct vmbus_softc *, struct vmbus_channel *); @@ -349,7 +349,6 @@ vmbus_chan_open_br(struct vmbus_channel const void *udata, int udlen, vmbus_chan_callback_t cb, void *cbarg) { struct vmbus_softc *sc = chan->ch_vmbus; - const struct vmbus_chanmsg_chopen_resp *resp; const struct vmbus_message *msg; struct vmbus_chanmsg_chopen *req; struct vmbus_msghc *mh; @@ -453,9 +452,50 @@ vmbus_chan_open_br(struct vmbus_channel goto failed; } - msg = vmbus_msghc_wait_result(sc, mh); - resp = (const struct vmbus_chanmsg_chopen_resp *)msg->msg_data; - status = resp->chm_status; + for (;;) { + msg = vmbus_msghc_poll_result(sc, mh); + if (msg != NULL) + break; + if (vmbus_chan_is_revoked(chan)) { + int i; + + /* + * NOTE: + * Hypervisor does _not_ send response CHOPEN to + * a revoked channel. + */ + vmbus_chan_printf(chan, + "chan%u is revoked, when it is being opened\n", + chan->ch_id); + + /* + * XXX + * Add extra delay before cancel the hypercall + * execution; mainly to close any possible + * CHRESCIND and CHOPEN_RESP races on the + * hypervisor side. + */ +#define REVOKE_LINGER 100 + for (i = 0; i < REVOKE_LINGER; ++i) { + msg = vmbus_msghc_poll_result(sc, mh); + if (msg != NULL) + break; + pause("rchopen", 1); + } +#undef REVOKE_LINGER + if (msg == NULL) + vmbus_msghc_exec_cancel(sc, mh); + break; + } + pause("chopen", 1); + } + if (msg != NULL) { + status = ((const struct vmbus_chanmsg_chopen_resp *) + msg->msg_data)->chm_status; + } else { + /* XXX any non-0 value is ok here. */ + status = 0xff; + } vmbus_msghc_put(sc, mh); @@ -620,7 +660,7 @@ vmbus_chan_gpadl_connect(struct vmbus_ch } static bool -vmbus_chan_wait_revoke(const struct vmbus_channel *chan) +vmbus_chan_wait_revoke(const struct vmbus_channel *chan, bool can_sleep) { #define WAIT_COUNT 200 /* 200ms */ @@ -629,8 +669,10 @@ vmbus_chan_wait_revoke(const struct vmbu for (i = 0; i < WAIT_COUNT; ++i) { if (vmbus_chan_is_revoked(chan)) return (true); - /* Not sure about the context; use busy-wait. */ - DELAY(1000); + if (can_sleep) + pause("wchrev", 1); + else + DELAY(1000); } return (false); @@ -667,7 +709,7 @@ vmbus_chan_gpadl_disconnect(struct vmbus if (error) { vmbus_msghc_put(sc, mh); - if (vmbus_chan_wait_revoke(chan)) { + if (vmbus_chan_wait_revoke(chan, true)) { /* * Error is benign; this channel is revoked, * so this GPADL will not be touched anymore. Modified: stable/11/sys/dev/hyperv/vmbus/vmbus_var.h ============================================================================== --- stable/11/sys/dev/hyperv/vmbus/vmbus_var.h Thu Jan 5 05:41:33 2017 (r311366) +++ stable/11/sys/dev/hyperv/vmbus/vmbus_var.h Thu Jan 5 05:46:06 2017 (r311367) @@ -160,9 +160,14 @@ void vmbus_msghc_put(struct vmbus_softc void *vmbus_msghc_dataptr(struct vmbus_msghc *); int vmbus_msghc_exec_noresult(struct vmbus_msghc *); int vmbus_msghc_exec(struct vmbus_softc *, struct vmbus_msghc *); +void vmbus_msghc_exec_cancel(struct vmbus_softc *, + struct vmbus_msghc *); const struct vmbus_message * vmbus_msghc_wait_result(struct vmbus_softc *, struct vmbus_msghc *); +const struct vmbus_message * + vmbus_msghc_poll_result(struct vmbus_softc *, + struct vmbus_msghc *); void vmbus_msghc_wakeup(struct vmbus_softc *, const struct vmbus_message *); void vmbus_msghc_reset(struct vmbus_msghc *, size_t); Modified: stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c ============================================================================== --- stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Jan 5 05:41:33 2017 (r311366) +++ stable/11/sys/dev/hyperv/vmbus/vmbus_xact.c Thu Jan 5 05:46:06 2017 (r311367) @@ -71,8 +71,10 @@ static struct vmbus_xact *vmbus_xact_all static void vmbus_xact_free(struct vmbus_xact *); static struct vmbus_xact *vmbus_xact_get1(struct vmbus_xact_ctx *, uint32_t); -const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, +static const void *vmbus_xact_wait1(struct vmbus_xact *, size_t *, bool); +static const void *vmbus_xact_return(struct vmbus_xact *, + size_t *); static void vmbus_xact_save_resp(struct vmbus_xact *, const void *, size_t); static void vmbus_xact_ctx_free(struct vmbus_xact_ctx *); @@ -277,27 +279,13 @@ vmbus_xact_deactivate(struct vmbus_xact mtx_unlock(&ctx->xc_lock); } -const void * -vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, - bool can_sleep) +static const void * +vmbus_xact_return(struct vmbus_xact *xact, size_t *resp_len) { struct vmbus_xact_ctx *ctx = xact->x_ctx; const void *resp; - mtx_lock(&ctx->xc_lock); - - KASSERT(ctx->xc_active == xact, ("xact mismatch")); - while (xact->x_resp == NULL && - (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { - if (can_sleep) { - mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0, - "wxact", 0); - } else { - mtx_unlock(&ctx->xc_lock); - DELAY(1000); - mtx_lock(&ctx->xc_lock); - } - } + mtx_assert(&ctx->xc_lock, MA_OWNED); KASSERT(ctx->xc_active == xact, ("xact trashed")); if ((ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) && xact->x_resp == NULL) { @@ -317,6 +305,32 @@ vmbus_xact_wait1(struct vmbus_xact *xact resp = xact->x_resp; *resp_len = xact->x_resp_len; + return (resp); +} + +static const void * +vmbus_xact_wait1(struct vmbus_xact *xact, size_t *resp_len, + bool can_sleep) +{ + struct vmbus_xact_ctx *ctx = xact->x_ctx; + const void *resp; + + mtx_lock(&ctx->xc_lock); + + KASSERT(ctx->xc_active == xact, ("xact mismatch")); + while (xact->x_resp == NULL && + (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { + if (can_sleep) { + mtx_sleep(&ctx->xc_active, &ctx->xc_lock, 0, + "wxact", 0); + } else { + mtx_unlock(&ctx->xc_lock); + DELAY(1000); + mtx_lock(&ctx->xc_lock); + } + } + resp = vmbus_xact_return(xact, resp_len); + mtx_unlock(&ctx->xc_lock); return (resp); @@ -336,6 +350,28 @@ vmbus_xact_busywait(struct vmbus_xact *x return (vmbus_xact_wait1(xact, resp_len, false /* can't sleep */)); } +const void * +vmbus_xact_poll(struct vmbus_xact *xact, size_t *resp_len) +{ + struct vmbus_xact_ctx *ctx = xact->x_ctx; + const void *resp; + + mtx_lock(&ctx->xc_lock); + + KASSERT(ctx->xc_active == xact, ("xact mismatch")); + if (xact->x_resp == NULL && + (ctx->xc_flags & VMBUS_XACT_CTXF_DESTROY) == 0) { + mtx_unlock(&ctx->xc_lock); + *resp_len = 0; + return (NULL); + } + resp = vmbus_xact_return(xact, resp_len); + + mtx_unlock(&ctx->xc_lock); + + return (resp); +} + static void vmbus_xact_save_resp(struct vmbus_xact *xact, const void *data, size_t dlen) {