From patchwork Mon Mar 21 05:25:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 8629551 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 45CF29F8A8 for ; Mon, 21 Mar 2016 05:27:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6413A20225 for ; Mon, 21 Mar 2016 05:27:18 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5225B2026D for ; Mon, 21 Mar 2016 05:27:17 +0000 (UTC) Received: from localhost ([::1]:55701 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ahsN2-0003Gu-NX for patchwork-qemu-devel@patchwork.kernel.org; Mon, 21 Mar 2016 01:27:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34625) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ahsLv-0001R7-6B for qemu-devel@nongnu.org; Mon, 21 Mar 2016 01:26:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ahsLt-0006he-He for qemu-devel@nongnu.org; Mon, 21 Mar 2016 01:26:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59198) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ahsLt-0006hN-7q for qemu-devel@nongnu.org; Mon, 21 Mar 2016 01:26:05 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id E5B637F08F for ; Mon, 21 Mar 2016 05:26:04 +0000 (UTC) Received: from jason-ThinkPad-T430s.redhat.com (vpn1-7-3.pek2.redhat.com [10.72.7.3]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2L5Puou017525; Mon, 21 Mar 2016 01:26:01 -0400 From: Jason Wang To: mst@redhat.com, qemu-devel@nongnu.org Date: Mon, 21 Mar 2016 13:25:55 +0800 Message-Id: <1458537955-8032-3-git-send-email-jasowang@redhat.com> In-Reply-To: <1458537955-8032-1-git-send-email-jasowang@redhat.com> References: <1458537955-8032-1-git-send-email-jasowang@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Jason Wang Subject: [Qemu-devel] [PATCH 2/2] tap: vhost busy polling support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch add the capability of basic vhost net busy polling which is supported by recent kernel. User could configure the maximum number of us that could be spent on busy polling through a new property of tap "vhost_poll_us". Signed-off-by: Jason Wang --- hw/net/vhost_net.c | 2 +- hw/scsi/vhost-scsi.c | 2 +- hw/virtio/vhost-backend.c | 8 ++++++++ hw/virtio/vhost.c | 40 ++++++++++++++++++++++++++++++++++++++- include/hw/virtio/vhost-backend.h | 3 +++ include/hw/virtio/vhost.h | 3 ++- include/net/vhost_net.h | 1 + net/tap.c | 10 ++++++++-- net/vhost-user.c | 1 + qapi-schema.json | 3 ++- 10 files changed, 66 insertions(+), 7 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 6e1032f..1840c73 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -166,7 +166,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) } r = vhost_dev_init(&net->dev, options->opaque, - options->backend_type); + options->backend_type, options->busyloop_timeout); if (r < 0) { goto fail; } diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index c86622c..f61483a 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -246,7 +246,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) s->dev.backend_features = 0; ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd, - VHOST_BACKEND_TYPE_KERNEL); + VHOST_BACKEND_TYPE_KERNEL, 0); if (ret < 0) { error_setg(errp, "vhost-scsi: vhost initialization failed: %s", strerror(-ret)); diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index b358902..d62372e 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -138,6 +138,12 @@ static int vhost_kernel_set_vring_call(struct vhost_dev *dev, return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file); } +static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev, + struct vhost_vring_state *s) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_BUSYLOOP_TIMEOUT, s); +} + static int vhost_kernel_set_features(struct vhost_dev *dev, uint64_t features) { @@ -185,6 +191,8 @@ static const VhostOps kernel_ops = { .vhost_get_vring_base = vhost_kernel_get_vring_base, .vhost_set_vring_kick = vhost_kernel_set_vring_kick, .vhost_set_vring_call = vhost_kernel_set_vring_call, + .vhost_set_vring_busyloop_timeout = + vhost_kernel_set_vring_busyloop_timeout, .vhost_set_features = vhost_kernel_set_features, .vhost_get_features = vhost_kernel_get_features, .vhost_set_owner = vhost_kernel_set_owner, diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 392d848..6a3e82f 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -963,6 +963,28 @@ static void vhost_eventfd_del(MemoryListener *listener, { } +static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev, + int n, uint32_t timeout) +{ + int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, n); + struct vhost_vring_state state = { + .index = vhost_vq_index, + .num = timeout, + }; + int r; + + if (!dev->vhost_ops->vhost_set_vring_busyloop_timeout) { + return -EINVAL; + } + + r = dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &state); + if (r) { + return r; + } + + return 0; +} + static int vhost_virtqueue_init(struct vhost_dev *dev, struct vhost_virtqueue *vq, int n) { @@ -993,7 +1015,7 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) } int vhost_dev_init(struct vhost_dev *hdev, void *opaque, - VhostBackendType backend_type) + VhostBackendType backend_type, uint32_t busyloop_timeout) { uint64_t features; int i, r; @@ -1034,6 +1056,17 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, goto fail_vq; } } + + if (busyloop_timeout) { + for (i = 0; i < hdev->nvqs; ++i) { + r = vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, + busyloop_timeout); + if (r < 0) { + goto fail_busyloop; + } + } + } + hdev->features = features; hdev->memory_listener = (MemoryListener) { @@ -1076,6 +1109,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->memory_changed = false; memory_listener_register(&hdev->memory_listener, &address_space_memory); return 0; +fail_busyloop: + while (--i >= 0) { + vhost_virtqueue_set_busyloop_timeout(hdev, hdev->vq_index + i, 0); + } + i = hdev->nvqs; fail_vq: while (--i >= 0) { vhost_virtqueue_cleanup(hdev->vqs + i); diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index 95fcc96..84e1cb7 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -57,6 +57,8 @@ typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev, struct vhost_vring_file *file); typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev, struct vhost_vring_file *file); +typedef int (*vhost_set_vring_busyloop_timeout_op)(struct vhost_dev *dev, + struct vhost_vring_state *r); typedef int (*vhost_set_features_op)(struct vhost_dev *dev, uint64_t features); typedef int (*vhost_get_features_op)(struct vhost_dev *dev, @@ -91,6 +93,7 @@ typedef struct VhostOps { vhost_get_vring_base_op vhost_get_vring_base; vhost_set_vring_kick_op vhost_set_vring_kick; vhost_set_vring_call_op vhost_set_vring_call; + vhost_set_vring_busyloop_timeout_op vhost_set_vring_busyloop_timeout; vhost_set_features_op vhost_set_features; vhost_get_features_op vhost_get_features; vhost_set_owner_op vhost_set_owner; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index b60d758..2106ed8 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -64,7 +64,8 @@ struct vhost_dev { }; int vhost_dev_init(struct vhost_dev *hdev, void *opaque, - VhostBackendType backend_type); + VhostBackendType backend_type, + uint32_t busyloop_timeout); void vhost_dev_cleanup(struct vhost_dev *hdev); int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 3389b41..8354b98 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -10,6 +10,7 @@ typedef struct vhost_net VHostNetState; typedef struct VhostNetOptions { VhostBackendType backend_type; NetClientState *net_backend; + uint32_t busyloop_timeout; void *opaque; } VhostNetOptions; diff --git a/net/tap.c b/net/tap.c index 8f790d1..90f12c7 100644 --- a/net/tap.c +++ b/net/tap.c @@ -661,6 +661,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, options.backend_type = VHOST_BACKEND_TYPE_KERNEL; options.net_backend = &s->nc; + if (tap->has_vhost_poll_us) { + options.busyloop_timeout = tap->vhost_poll_us; + } else { + options.busyloop_timeout = 0; + } if (vhostfdname) { vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); @@ -684,8 +689,9 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, "vhost-net requested but could not be initialized"); return; } - } else if (vhostfdname) { - error_setg(errp, "vhostfd= is not valid without vhost"); + } else if (vhostfdname || tap->has_vhost_poll_us) { + error_setg(errp, "vhostfd(s)= or vhost_poll_us= is not valid" + " without vhost"); } } diff --git a/net/vhost-user.c b/net/vhost-user.c index 1b9e73a..b200182 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -80,6 +80,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[]) options.net_backend = ncs[i]; options.opaque = s->chr; + options.busyloop_timeout = 0; s->vhost_net = vhost_net_init(&options); if (!s->vhost_net) { error_report("failed to init vhost_net for queue %d", i); diff --git a/qapi-schema.json b/qapi-schema.json index 88f9b81..ea56a01 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2532,7 +2532,8 @@ '*vhostfd': 'str', '*vhostfds': 'str', '*vhostforce': 'bool', - '*queues': 'uint32'} } + '*queues': 'uint32', + '*vhost_poll_us': 'uint32'} } ## # @NetdevSocketOptions