From 6c4e9d487fea67ceaebf5942be5b76ed675d0e9a Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 20 Aug 2019 18:06:13 +0200 Subject: [PATCH 1/6] rng-builtin: add an RNG backend that uses qemu_guest_getrandom() Add a new RNG backend using QEMU builtin getrandom function. It can be created and used with something like: ... -object rng-builtin,id=rng0 -device virtio-rng,rng=rng0 ... Signed-off-by: Laurent Vivier Message-Id: <20190820160615.14616-2-lvivier@redhat.com> --- backends/Makefile.objs | 2 +- backends/rng-builtin.c | 78 ++++++++++++++++++++++++++++++++++++++++++ qemu-options.hx | 7 ++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 backends/rng-builtin.c diff --git a/backends/Makefile.objs b/backends/Makefile.objs index 981e8e122f..f0691116e8 100644 --- a/backends/Makefile.objs +++ b/backends/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y += rng.o rng-egd.o +common-obj-y += rng.o rng-egd.o rng-builtin.o common-obj-$(CONFIG_POSIX) += rng-random.o common-obj-$(CONFIG_TPM) += tpm.o diff --git a/backends/rng-builtin.c b/backends/rng-builtin.c new file mode 100644 index 0000000000..3381d47174 --- /dev/null +++ b/backends/rng-builtin.c @@ -0,0 +1,78 @@ +/* + * QEMU Builtin Random Number Generator Backend + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "sysemu/rng.h" +#include "qemu/main-loop.h" +#include "qemu/guest-random.h" + +#define TYPE_RNG_BUILTIN "rng-builtin" +#define RNG_BUILTIN(obj) OBJECT_CHECK(RngBuiltin, (obj), TYPE_RNG_BUILTIN) + +typedef struct RngBuiltin { + RngBackend parent; + QEMUBH *bh; +} RngBuiltin; + +static void rng_builtin_receive_entropy_bh(void *opaque) +{ + RngBuiltin *s = opaque; + + while (!QSIMPLEQ_EMPTY(&s->parent.requests)) { + RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests); + + qemu_guest_getrandom_nofail(req->data, req->size); + + req->receive_entropy(req->opaque, req->data, req->size); + + rng_backend_finalize_request(&s->parent, req); + } +} + +static void rng_builtin_request_entropy(RngBackend *b, RngRequest *req) +{ + RngBuiltin *s = RNG_BUILTIN(b); + + qemu_bh_schedule(s->bh); +} + +static void rng_builtin_init(Object *obj) +{ + RngBuiltin *s = RNG_BUILTIN(obj); + + s->bh = qemu_bh_new(rng_builtin_receive_entropy_bh, s); +} + +static void rng_builtin_finalize(Object *obj) +{ + RngBuiltin *s = RNG_BUILTIN(obj); + + qemu_bh_delete(s->bh); +} + +static void rng_builtin_class_init(ObjectClass *klass, void *data) +{ + RngBackendClass *rbc = RNG_BACKEND_CLASS(klass); + + rbc->request_entropy = rng_builtin_request_entropy; +} + +static const TypeInfo rng_builtin_info = { + .name = TYPE_RNG_BUILTIN, + .parent = TYPE_RNG_BACKEND, + .instance_size = sizeof(RngBuiltin), + .instance_init = rng_builtin_init, + .instance_finalize = rng_builtin_finalize, + .class_init = rng_builtin_class_init, +}; + +static void register_types(void) +{ + type_register_static(&rng_builtin_info); +} + +type_init(register_types); diff --git a/qemu-options.hx b/qemu-options.hx index ea0638e92d..a8b70d946f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4332,6 +4332,13 @@ other options. The @option{share} boolean option is @var{on} by default with memfd. +@item -object rng-builtin,id=@var{id} + +Creates a random number generator backend which obtains entropy from +QEMU builtin functions. The @option{id} parameter is a unique ID that +will be used to reference this entropy backend from the @option{virtio-rng} +device. + @item -object rng-random,id=@var{id},filename=@var{/dev/random} Creates a random number generator backend which obtains entropy from From 5f7655f6ef1583c4b15c5a6e1aa2348538f6104b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 20 Aug 2019 18:06:14 +0200 Subject: [PATCH 2/6] virtio-rng: Keep the default backend out of VirtIORNGConf The default backend is only used within virtio_rng_device_realize(). Replace VirtIORNGConf member default_backend by a local variable. Adjust its type to reduce conversions. While there, pass &error_abort instead of NULL when failure would be a programming error. Signed-off-by: Markus Armbruster Signed-off-by: Laurent Vivier Message-Id: <20190820160615.14616-3-lvivier@redhat.com> --- hw/virtio/virtio-rng.c | 20 +++++++++----------- include/hw/virtio/virtio-rng.h | 2 -- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index d1650e1dee..fcf3b2e329 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -19,6 +19,7 @@ #include "hw/virtio/virtio-rng.h" #include "sysemu/rng.h" #include "sysemu/runstate.h" +#include "sysemu/rng-random.h" #include "qom/object_interfaces.h" #include "trace.h" @@ -192,27 +193,24 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) } if (vrng->conf.rng == NULL) { - vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM)); + Object *default_backend = object_new(TYPE_RNG_RANDOM); - user_creatable_complete(USER_CREATABLE(vrng->conf.default_backend), + user_creatable_complete(USER_CREATABLE(default_backend), &local_err); if (local_err) { error_propagate(errp, local_err); - object_unref(OBJECT(vrng->conf.default_backend)); + object_unref(default_backend); return; } - object_property_add_child(OBJECT(dev), - "default-backend", - OBJECT(vrng->conf.default_backend), - NULL); + object_property_add_child(OBJECT(dev), "default-backend", + default_backend, &error_abort); /* The child property took a reference, we can safely drop ours now */ - object_unref(OBJECT(vrng->conf.default_backend)); + object_unref(default_backend); - object_property_set_link(OBJECT(dev), - OBJECT(vrng->conf.default_backend), - "rng", NULL); + object_property_set_link(OBJECT(dev), default_backend, + "rng", &error_abort); } vrng->rng = vrng->conf.rng; diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index ff699335e3..bd05d734b8 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -14,7 +14,6 @@ #include "hw/virtio/virtio.h" #include "sysemu/rng.h" -#include "sysemu/rng-random.h" #include "standard-headers/linux/virtio_rng.h" #define TYPE_VIRTIO_RNG "virtio-rng-device" @@ -27,7 +26,6 @@ struct VirtIORNGConf { RngBackend *rng; uint64_t max_bytes; uint32_t period_ms; - RngRandom *default_backend; }; typedef struct VirtIORNG { From 0198c2621a1e57d4ceaca1326897f007963c12df Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 20 Aug 2019 18:06:15 +0200 Subject: [PATCH 3/6] virtio-rng: change default backend to rng-builtin Reviewed-by: Markus Armbruster Signed-off-by: Laurent Vivier Message-Id: <20190820160615.14616-4-lvivier@redhat.com> --- backends/rng-builtin.c | 1 - hw/virtio/virtio-rng.c | 3 +-- include/sysemu/rng.h | 2 ++ qemu-options.hx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backends/rng-builtin.c b/backends/rng-builtin.c index 3381d47174..ba1b8d66b8 100644 --- a/backends/rng-builtin.c +++ b/backends/rng-builtin.c @@ -10,7 +10,6 @@ #include "qemu/main-loop.h" #include "qemu/guest-random.h" -#define TYPE_RNG_BUILTIN "rng-builtin" #define RNG_BUILTIN(obj) OBJECT_CHECK(RngBuiltin, (obj), TYPE_RNG_BUILTIN) typedef struct RngBuiltin { diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index fcf3b2e329..e93bed020f 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -19,7 +19,6 @@ #include "hw/virtio/virtio-rng.h" #include "sysemu/rng.h" #include "sysemu/runstate.h" -#include "sysemu/rng-random.h" #include "qom/object_interfaces.h" #include "trace.h" @@ -193,7 +192,7 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) } if (vrng->conf.rng == NULL) { - Object *default_backend = object_new(TYPE_RNG_RANDOM); + Object *default_backend = object_new(TYPE_RNG_BUILTIN); user_creatable_complete(USER_CREATABLE(default_backend), &local_err); diff --git a/include/sysemu/rng.h b/include/sysemu/rng.h index 9b22c156f8..fa6eada78c 100644 --- a/include/sysemu/rng.h +++ b/include/sysemu/rng.h @@ -24,6 +24,8 @@ #define RNG_BACKEND_CLASS(klass) \ OBJECT_CLASS_CHECK(RngBackendClass, (klass), TYPE_RNG_BACKEND) +#define TYPE_RNG_BUILTIN "rng-builtin" + typedef struct RngRequest RngRequest; typedef struct RngBackendClass RngBackendClass; typedef struct RngBackend RngBackend; diff --git a/qemu-options.hx b/qemu-options.hx index a8b70d946f..b2ba7c501d 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4337,7 +4337,7 @@ The @option{share} boolean option is @var{on} by default with memfd. Creates a random number generator backend which obtains entropy from QEMU builtin functions. The @option{id} parameter is a unique ID that will be used to reference this entropy backend from the @option{virtio-rng} -device. +device. By default, the @option{virtio-rng} device uses this RNG backend. @item -object rng-random,id=@var{id},filename=@var{/dev/random} From eb1556c493d8abc5bfc8685561bcea934700e200 Mon Sep 17 00:00:00 2001 From: Julia Suvorova Date: Tue, 20 Aug 2019 18:30:05 +0200 Subject: [PATCH 4/6] virtio-pci: Add Function Level Reset support Using FLR becomes convenient in cases where resetting the bus is impractical, for example, when debugging the behavior of individual functions. Signed-off-by: Julia Suvorova Message-Id: <20190820163005.1880-1-jusual@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/core/machine.c | 4 +++- hw/virtio/virtio-pci.c | 10 ++++++++++ hw/virtio/virtio-pci.h | 4 ++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index 83cd1bfeec..829ada099e 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -27,7 +27,9 @@ #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" -GlobalProperty hw_compat_4_1[] = {}; +GlobalProperty hw_compat_4_1[] = { + { "virtio-pci", "x-pcie-flr-init", "off" }, +}; const size_t hw_compat_4_1_len = G_N_ELEMENTS(hw_compat_4_1); GlobalProperty hw_compat_4_0[] = { diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 8babd92e59..0075b3e2af 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -601,6 +601,10 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, pci_default_write_config(pci_dev, address, val, len); + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_FLR) { + pcie_cap_flr_write_config(pci_dev, address, val, len); + } + if (range_covers_byte(address, len, PCI_COMMAND) && !(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER)) { virtio_pci_stop_ioeventfd(proxy); @@ -1777,6 +1781,10 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) pcie_ats_init(pci_dev, 256); } + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_FLR) { + /* Set Function Level Reset capability bit */ + pcie_cap_flr_init(pci_dev); + } } else { /* * make future invocations of pci_is_express() return false @@ -1844,6 +1852,8 @@ static Property virtio_pci_properties[] = { VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, true), DEFINE_PROP_BIT("x-pcie-pm-init", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_INIT_PM_BIT, true), + DEFINE_PROP_BIT("x-pcie-flr-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_FLR_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 292275acb1..e2eaaa9182 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -44,6 +44,7 @@ enum { VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, VIRTIO_PCI_FLAG_INIT_PM_BIT, + VIRTIO_PCI_FLAG_INIT_FLR_BIT, }; /* Need to activate work-arounds for buggy guests at vmstate load. */ @@ -80,6 +81,9 @@ enum { /* Init Power Management */ #define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT) +/* Init Function Level Reset capability */ +#define VIRTIO_PCI_FLAG_INIT_FLR (1 << VIRTIO_PCI_FLAG_INIT_FLR_BIT) + typedef struct { MSIMessage msg; int virq; From 8726b70b449896f1211f869ec4f608904f027207 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 3 Sep 2019 23:04:22 +0300 Subject: [PATCH 5/6] libvhost-user: fix SLAVE_SEND_FD handling It doesn't look like this could possibly work properly since VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD is defined to 10, but the dev->protocol_features has a bitmap. I suppose the peer this was tested with also supported VHOST_USER_PROTOCOL_F_LOG_SHMFD, in which case the test would always be false, but nevertheless the code seems wrong. Use has_feature() to fix this. Fixes: d84599f56c82 ("libvhost-user: support host notifier") Signed-off-by: Johannes Berg Message-Id: <20190903200422.11693-1-johannes@sipsolutions.net> Reviewed-by: Tiwei Bie Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- contrib/libvhost-user/libvhost-user.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index 4b36e35a82..cb5f5770e4 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -1097,7 +1097,8 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, vmsg.fd_num = fd_num; - if ((dev->protocol_features & VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) == 0) { + if (!has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD)) { return false; } From eeb39263aa9b05b4ac3f8d8e957958071834a7b6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 4 Sep 2019 09:50:21 +0300 Subject: [PATCH 6/6] libvhost-user: introduce and use vu_has_protocol_feature() This simplifies the various has_feature() checks, we already have vu_has_feature() but it checks features, not protocol features. Signed-off-by: Johannes Berg Message-Id: <20190904065021.1360-1-johannes@sipsolutions.net> Reviewed-by: Tiwei Bie Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- contrib/libvhost-user/libvhost-user.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contrib/libvhost-user/libvhost-user.c b/contrib/libvhost-user/libvhost-user.c index cb5f5770e4..68c27136ae 100644 --- a/contrib/libvhost-user/libvhost-user.c +++ b/contrib/libvhost-user/libvhost-user.c @@ -94,6 +94,11 @@ bool vu_has_feature(VuDev *dev, return has_feature(dev->features, fbit); } +static inline bool vu_has_protocol_feature(VuDev *dev, unsigned int fbit) +{ + return has_feature(dev->protocol_features, fbit); +} + static const char * vu_request_to_string(unsigned int req) { @@ -951,8 +956,7 @@ vu_check_queue_inflights(VuDev *dev, VuVirtq *vq) { int i = 0; - if (!has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { + if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { return 0; } @@ -1097,8 +1101,7 @@ bool vu_set_queue_host_notifier(VuDev *dev, VuVirtq *vq, int fd, vmsg.fd_num = fd_num; - if (!has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD)) { + if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD)) { return false; } @@ -2191,8 +2194,7 @@ vu_queue_map_desc(VuDev *dev, VuVirtq *vq, unsigned int idx, size_t sz) static int vu_queue_inflight_get(VuDev *dev, VuVirtq *vq, int desc_idx) { - if (!has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { + if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { return 0; } @@ -2209,8 +2211,7 @@ vu_queue_inflight_get(VuDev *dev, VuVirtq *vq, int desc_idx) static int vu_queue_inflight_pre_put(VuDev *dev, VuVirtq *vq, int desc_idx) { - if (!has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { + if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { return 0; } @@ -2226,8 +2227,7 @@ vu_queue_inflight_pre_put(VuDev *dev, VuVirtq *vq, int desc_idx) static int vu_queue_inflight_post_put(VuDev *dev, VuVirtq *vq, int desc_idx) { - if (!has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { + if (!vu_has_protocol_feature(dev, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)) { return 0; }