From patchwork Thu Jan 23 15:17:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 11348735 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1255F92A for ; Thu, 23 Jan 2020 16:59:13 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D9E0121D7E for ; Thu, 23 Jan 2020 16:59:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="WXJ+9z7G" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D9E0121D7E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:32878 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iufp1-0000Cd-It for patchwork-qemu-devel@patchwork.kernel.org; Thu, 23 Jan 2020 11:59:11 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45771) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iueET-0005nD-Eu for qemu-devel@nongnu.org; Thu, 23 Jan 2020 10:17:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iueEQ-0002m6-Up for qemu-devel@nongnu.org; Thu, 23 Jan 2020 10:17:21 -0500 Received: from us-smtp-2.mimecast.com ([207.211.31.81]:25992 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iueEQ-0002lv-RS for qemu-devel@nongnu.org; Thu, 23 Jan 2020 10:17:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1579792638; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=aeXBkPxcRcComiL4taCcDIFuNqJYa52PmMTzUfstOgo=; b=WXJ+9z7Gu7RdrDuke5OjoHj+Vm61oam9X/SxW2K0skRN6g0Z+SuIdxf+V+lUGdCWDmMNdX vCwVK+4H66X5lU4y0x0XXB6fz3Lwsr85lJ6bqt7mJXZK0bviiF/gXSjXPoRoDDLc/e8Pc2 lEv0EdNT94QWjBzIVy9HLCFyqf+K8t8= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-425-e0b89CPCPfmogjhjGqHUBA-1; Thu, 23 Jan 2020 10:17:11 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 75664190B2A9; Thu, 23 Jan 2020 15:17:10 +0000 (UTC) Received: from thinkpad.redhat.com (ovpn-204-119.brq.redhat.com [10.40.204.119]) by smtp.corp.redhat.com (Postfix) with ESMTP id A13665DA87; Thu, 23 Jan 2020 15:17:08 +0000 (UTC) From: Laurent Vivier To: qemu-devel@nongnu.org Subject: [RFC 2/2] virtio-rng: add a control queue Date: Thu, 23 Jan 2020 16:17:00 +0100 Message-Id: <20200123151700.1367857-3-lvivier@redhat.com> In-Reply-To: <20200123151700.1367857-1-lvivier@redhat.com> References: <20200123151700.1367857-1-lvivier@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-MC-Unique: e0b89CPCPfmogjhjGqHUBA-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 207.211.31.81 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier , Amit Shah , Eduardo Habkost , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" When the linux kernel wants to switch to another device it needs to be able to flush the on-fly requests. Signed-off-by: Laurent Vivier --- hw/core/machine.c | 1 + hw/virtio/trace-events | 6 ++ hw/virtio/virtio-rng.c | 81 ++++++++++++++++++++- include/hw/virtio/virtio-rng.h | 3 +- include/standard-headers/linux/virtio_rng.h | 14 ++++ 5 files changed, 101 insertions(+), 4 deletions(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 3e288bfceb7f..6c417dbdc02a 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -34,6 +34,7 @@ GlobalProperty hw_compat_4_2[] = { { "vhost-blk-device", "seg_max_adjust", "off"}, { "usb-host", "suppress-remote-wake", "off" }, { "usb-redir", "suppress-remote-wake", "off" }, + { "virtio-rng", "ctrl-queue", "off" }, }; const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2); diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index e28ba48da621..95b77f3a3056 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -38,6 +38,12 @@ virtio_rng_popped(void *rng) "rng %p: elem popped" virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed" virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left" virtio_rng_vm_state_change(void *rng, int running, int state) "rng %p: state change to running %d state %d" +virtio_rng_ctrl(void *rng) "rng %p" +virtio_rng_ctrl_popped(void *rng) "rng %p" +virtio_rng_ctrl_pushed(void *rng) "rng %p" +virtio_rng_flush(void *rng) "rng %p" +virtio_rng_flush_popped(void *rng) "rng %p" +virtio_rng_flush_pushed(void *rng) "rng %p" # virtio-balloon.c # diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index a0bca55bef55..389aa8997f3d 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -128,9 +128,76 @@ static void virtio_rng_handle_input(VirtIODevice *vdev, VirtQueue *vq) virtio_rng_process(vrng); } -static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp) +static virtio_rng_ctrl_ack virtio_rng_flush(VirtIORNG *vrng) { - return f; + VirtQueueElement *elem; + VirtIODevice *vdev = VIRTIO_DEVICE(vrng); + + trace_virtio_rng_flush(vrng); + while (!virtio_queue_empty(vrng->input_vq)) { + elem = virtqueue_pop(vrng->input_vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + trace_virtio_rng_flush_popped(vrng); + virtqueue_push(vrng->input_vq, elem, 0); + trace_virtio_rng_flush_pushed(vrng); + g_free(elem); + } + virtio_notify(vdev, vrng->input_vq); + + return VIRTIO_RNG_OK; +} + +static void virtio_rng_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) +{ + VirtIORNG *vrng = VIRTIO_RNG(vdev); + VirtQueueElement *elem; + virtio_rng_ctrl_ack status = VIRTIO_RNG_ERR; + struct virtio_rng_ctrl_hdr ctrl; + size_t s; + + trace_virtio_rng_ctrl(vrng); + for (;;) { + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + trace_virtio_rng_ctrl_popped(vrng); + + if (iov_size(elem->in_sg, elem->in_num) < sizeof(status) || + iov_size(elem->out_sg, elem->out_num) < sizeof(ctrl)) { + virtio_error(vdev, "virtio-rng ctrl missing headers"); + virtqueue_detach_element(vq, elem, 0); + g_free(elem); + break; + } + + s = iov_to_buf(elem->out_sg, elem->out_num, 0, &ctrl, sizeof(ctrl)); + if (s != sizeof(ctrl)) { + status = VIRTIO_RNG_ERR; + } else if (ctrl.cmd == VIRTIO_RNG_CMD_FLUSH) { + status = virtio_rng_flush(vrng); + } + + s = iov_from_buf(elem->in_sg, elem->in_num, 0, &status, sizeof(status)); + assert(s == sizeof(status)); + + virtqueue_push(vq, elem, sizeof(status)); + trace_virtio_rng_ctrl_pushed(vrng); + virtio_notify(vdev, vq); + g_free(elem); + } +} + +static uint64_t virtio_rng_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + VirtIORNG *vrng = VIRTIO_RNG(vdev); + + features |= vrng->conf.host_features; + + return features; } static void virtio_rng_vm_state_change(void *opaque, int running, @@ -221,6 +288,9 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0); vrng->input_vq = virtio_add_queue(vdev, 8, virtio_rng_handle_input); + if (virtio_has_feature(vrng->conf.host_features, VIRTIO_RNG_F_CTRL_VQ)) { + vrng->ctrl_vq = virtio_add_queue(vdev, 8, virtio_rng_handle_ctrl); + } vrng->quota_remaining = vrng->conf.max_bytes; vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, check_rate_limit, vrng); @@ -238,6 +308,9 @@ static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp) qemu_del_vm_change_state_handler(vrng->vmstate); timer_del(vrng->rate_limit_timer); timer_free(vrng->rate_limit_timer); + if (virtio_has_feature(vrng->conf.host_features, VIRTIO_RNG_F_CTRL_VQ)) { + virtio_delete_queue(vrng->ctrl_vq); + } virtio_delete_queue(vrng->input_vq); virtio_cleanup(vdev); } @@ -261,6 +334,8 @@ static Property virtio_rng_properties[] = { DEFINE_PROP_UINT64("max-bytes", VirtIORNG, conf.max_bytes, INT64_MAX), DEFINE_PROP_UINT32("period", VirtIORNG, conf.period_ms, 1 << 16), DEFINE_PROP_LINK("rng", VirtIORNG, conf.rng, TYPE_RNG_BACKEND, RngBackend *), + DEFINE_PROP_BIT64("ctrl-queue", VirtIORNG, conf.host_features, + VIRTIO_RNG_F_CTRL_VQ, true), DEFINE_PROP_END_OF_LIST(), }; @@ -274,7 +349,7 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_MISC, dc->categories); vdc->realize = virtio_rng_device_realize; vdc->unrealize = virtio_rng_device_unrealize; - vdc->get_features = get_features; + vdc->get_features = virtio_rng_get_features; vdc->set_status = virtio_rng_set_status; } diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index d77daf126828..abecec7b244a 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -26,13 +26,14 @@ struct VirtIORNGConf { RngBackend *rng; uint64_t max_bytes; uint32_t period_ms; + uint64_t host_features; }; typedef struct VirtIORNG { VirtIODevice parent_obj; - /* Only one vq - guest puts buffer(s) on it when it needs entropy */ VirtQueue *input_vq; + VirtQueue *ctrl_vq; VirtIORNGConf conf; diff --git a/include/standard-headers/linux/virtio_rng.h b/include/standard-headers/linux/virtio_rng.h index 60fc798bde18..b80e9298817e 100644 --- a/include/standard-headers/linux/virtio_rng.h +++ b/include/standard-headers/linux/virtio_rng.h @@ -5,4 +5,18 @@ #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_config.h" +/* The features bitmap for virtuio rng */ +#define VIRTIO_RNG_F_CTRL_VQ 0 /* Device has control queue */ + +struct virtio_rng_ctrl_hdr { + uint8_t cmd; +} QEMU_PACKED; + +#define VIRTIO_RNG_CMD_FLUSH 0 + +typedef uint8_t virtio_rng_ctrl_ack; + +#define VIRTIO_RNG_OK 0 +#define VIRTIO_RNG_ERR 1 + #endif /* _LINUX_VIRTIO_RNG_H */