From 0625343f0e53be7c02f32c09deed7565e5bee953 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sun, 30 Sep 2018 16:34:15 +0200 Subject: [PATCH] kernel: Bring in a port of FreeBSD's virtio_random(4) driver. Tested-by: Diederik de Groot --- share/man/man4/Makefile | 1 + share/man/man4/virtio.4 | 3 +- share/man/man4/virtio_random.4 | 69 ++++++ sys/conf/files | 1 + sys/config/LINT64 | 1 + sys/dev/virtual/virtio/Makefile | 2 +- sys/dev/virtual/virtio/{ => random}/Makefile | 9 +- sys/dev/virtual/virtio/random/virtio_random.c | 230 ++++++++++++++++++ sys/sys/random.h | 1 + 9 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 share/man/man4/virtio_random.4 copy sys/dev/virtual/virtio/{ => random}/Makefile (85%) create mode 100644 sys/dev/virtual/virtio/random/virtio_random.c diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 962d6990ba..7ce4e66684 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -383,6 +383,7 @@ MAN= aac.4 \ vinum.4 \ virtio.4 \ virtio_blk.4 \ + virtio_random.4 \ virtio_scsi.4 \ vlan.4 \ vmbus.4 \ diff --git a/share/man/man4/virtio.4 b/share/man/man4/virtio.4 index a193d38e6d..73c9a23fcf 100644 --- a/share/man/man4/virtio.4 +++ b/share/man/man4/virtio.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD: head/share/man/man4/virtio.4 273515 2014-10-23 04:47:32Z bryanv $ .\" -.Dd July 30, 2017 +.Dd September 30, 2018 .Dt VIRTIO 4 .Os .Sh NAME @@ -94,6 +94,7 @@ The default value is 0 (use MSI-X interrupts if available). .\".Xr virtio_balloon 4 , .Xr virtio_blk 4 , .\".Xr virtio_console 4 , +.Xr virtio_random 4 , .Xr virtio_scsi 4 , .Xr vtnet 4 .Sh HISTORY diff --git a/share/man/man4/virtio_random.4 b/share/man/man4/virtio_random.4 new file mode 100644 index 0000000000..3efe317fde --- /dev/null +++ b/share/man/man4/virtio_random.4 @@ -0,0 +1,69 @@ +.\" Copyright (c) 2013 Bryan Venteicher +.\" 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, 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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: head/share/man/man4/virtio_random.4 275990 2014-12-21 09:53:29Z brueffer $ +.\" +.Dd September 30, 2018 +.Dt VIRTIO_RANDOM 4 +.Os +.Sh NAME +.Nm virtio_random +.Nd VirtIO Entropy driver +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device virtio_random" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +virtio_random_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +device driver provides support for VirtIO entropy devices. +.Pp +The entropy device supplies high-quality randomness from the +hypervisor to the guest. +.Pp +See the URL in +.Sx SEE ALSO +for some instrunctions on how to test the +.Nm +driver. +.Sh SEE ALSO +.Xr random 4 , +.Xr virtio 4 +.Pp +.Pa https://fedoraproject.org/wiki/QA:Testcase_Virtualization_VirtioRNG +.Sh HISTORY +The +.Nm +driver was written by +.An Bryan Venteicher Aq Mt bryanv@FreeBSD.org . diff --git a/sys/conf/files b/sys/conf/files index f7b875c29d..042bb93e0b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2931,6 +2931,7 @@ dev/virtual/hyperv/vmbus/vmbus.c optional vmbus # virtio support # dev/virtual/virtio/block/virtio_blk.c optional virtio_blk virtio +dev/virtual/virtio/random/virtio_random.c optional virtio_random virtio dev/virtual/virtio/scsi/virtio_scsi.c optional virtio_scsi virtio dev/virtual/virtio/net/if_vtnet.c optional vtnet virtio dev/virtual/virtio/pci/virtio_pci.c optional virtio pci diff --git a/sys/config/LINT64 b/sys/config/LINT64 index dcfe465a49..071f782653 100644 --- a/sys/config/LINT64 +++ b/sys/config/LINT64 @@ -2126,6 +2126,7 @@ device vmbus # device virtio device virtio_blk +device virtio_random device virtio_scsi device vtnet diff --git a/sys/dev/virtual/virtio/Makefile b/sys/dev/virtual/virtio/Makefile index a528062c43..a53fc646c7 100644 --- a/sys/dev/virtual/virtio/Makefile +++ b/sys/dev/virtual/virtio/Makefile @@ -23,6 +23,6 @@ # SUCH DAMAGE. # -SUBDIR= virtio pci block net scsi +SUBDIR= virtio pci block net random scsi .include diff --git a/sys/dev/virtual/virtio/Makefile b/sys/dev/virtual/virtio/random/Makefile similarity index 85% copy from sys/dev/virtual/virtio/Makefile copy to sys/dev/virtual/virtio/random/Makefile index a528062c43..7126677a35 100644 --- a/sys/dev/virtual/virtio/Makefile +++ b/sys/dev/virtual/virtio/random/Makefile @@ -1,5 +1,5 @@ # -# $FreeBSD$ +# $FreeBSD: head/sys/modules/virtio/random/Makefile 314651 2017-03-04 10:10:17Z ngie $ # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -23,6 +23,9 @@ # SUCH DAMAGE. # -SUBDIR= virtio pci block net scsi +KMOD= virtio_random +SRCS= virtio_random.c +SRCS+= virtio_bus_if.h virtio_if.h +SRCS+= bus_if.h device_if.h -.include +.include diff --git a/sys/dev/virtual/virtio/random/virtio_random.c b/sys/dev/virtual/virtio/random/virtio_random.c new file mode 100644 index 0000000000..5d14265cdd --- /dev/null +++ b/sys/dev/virtual/virtio/random/virtio_random.c @@ -0,0 +1,230 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2013, Bryan Venteicher + * 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: head/sys/dev/virtio/random/virtio_random.c 338324 2018-08-26 12:51:46Z markm $ + */ + +/* Driver for VirtIO entropy device. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct vtrnd_softc { + device_t vtrnd_dev; + uint64_t vtrnd_features; + struct callout vtrnd_callout; + struct virtqueue *vtrnd_vq; +}; + +static int vtrnd_modevent(module_t, int, void *); + +static int vtrnd_probe(device_t); +static int vtrnd_attach(device_t); +static int vtrnd_detach(device_t); + +static void vtrnd_negotiate_features(struct vtrnd_softc *); +static int vtrnd_alloc_virtqueue(struct vtrnd_softc *); +static void vtrnd_harvest(struct vtrnd_softc *); +static void vtrnd_timer(void *); + +#define VTRND_FEATURES 0 + +static struct virtio_feature_desc vtrnd_feature_desc[] = { + { 0, NULL } +}; + +static device_method_t vtrnd_methods[] = { + /* Device methods. */ + DEVMETHOD(device_probe, vtrnd_probe), + DEVMETHOD(device_attach, vtrnd_attach), + DEVMETHOD(device_detach, vtrnd_detach), + + DEVMETHOD_END +}; + +static driver_t vtrnd_driver = { + "vtrnd", + vtrnd_methods, + sizeof(struct vtrnd_softc) +}; +static devclass_t vtrnd_devclass; + +DRIVER_MODULE(virtio_random, virtio_pci, vtrnd_driver, vtrnd_devclass, + vtrnd_modevent, 0); +MODULE_VERSION(virtio_random, 1); +MODULE_DEPEND(virtio_random, virtio, 1, 1, 1); + +static int +vtrnd_modevent(module_t mod, int type, void *unused) +{ + int error; + + switch (type) { + case MOD_LOAD: + case MOD_UNLOAD: + case MOD_SHUTDOWN: + error = 0; + break; + default: + error = EOPNOTSUPP; + break; + } + + return (error); +} + +static int +vtrnd_probe(device_t dev) +{ + + if (virtio_get_device_type(dev) != VIRTIO_ID_ENTROPY) + return (ENXIO); + + device_set_desc(dev, "VirtIO Entropy Adapter"); + + return (BUS_PROBE_DEFAULT); +} + +static int +vtrnd_attach(device_t dev) +{ + struct vtrnd_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->vtrnd_dev = dev; + + callout_init_mp(&sc->vtrnd_callout); + + virtio_set_feature_desc(dev, vtrnd_feature_desc); + vtrnd_negotiate_features(sc); + + error = vtrnd_alloc_virtqueue(sc); + if (error) { + device_printf(dev, "cannot allocate virtqueue\n"); + goto fail; + } + + callout_reset(&sc->vtrnd_callout, 5 * hz, vtrnd_timer, sc); + +fail: + if (error) + vtrnd_detach(dev); + + return (error); +} + +static int +vtrnd_detach(device_t dev) +{ + struct vtrnd_softc *sc; + + sc = device_get_softc(dev); + + callout_stop_sync(&sc->vtrnd_callout); + + return (0); +} + +static void +vtrnd_negotiate_features(struct vtrnd_softc *sc) +{ + device_t dev; + uint64_t features; + + dev = sc->vtrnd_dev; + features = VTRND_FEATURES; + + sc->vtrnd_features = virtio_negotiate_features(dev, features); +} + +static int +vtrnd_alloc_virtqueue(struct vtrnd_softc *sc) +{ + device_t dev; + struct vq_alloc_info vq_info; + + dev = sc->vtrnd_dev; + + VQ_ALLOC_INFO_INIT(&vq_info, 0, &sc->vtrnd_vq, + "%s request", device_get_nameunit(dev)); + + return (virtio_alloc_virtqueues(dev, 1, &vq_info)); +} + +static void +vtrnd_harvest(struct vtrnd_softc *sc) +{ + struct sglist_seg segs[1]; + struct sglist sg; + struct virtqueue *vq; + uint32_t value; + int error; + + vq = sc->vtrnd_vq; + + sglist_init(&sg, 1, segs); + error = sglist_append(&sg, &value, sizeof(value)); + KASSERT(error == 0 && sg.sg_nseg == 1, + ("%s: error %d adding buffer to sglist", __func__, error)); + + if (!virtqueue_empty(vq)) + return; + if (virtqueue_enqueue(vq, &value, &sg, 0, 1) != 0) + return; + + /* + * Poll for the response, but the command is likely already + * done when we return from the notify. + */ + virtqueue_notify(vq, NULL); + virtqueue_poll(vq, NULL); + + add_buffer_randomness_src((const char *)&value, sizeof(value), + RAND_SRC_VIRTIO); +} + +static void +vtrnd_timer(void *xsc) +{ + struct vtrnd_softc *sc; + + sc = xsc; + + vtrnd_harvest(sc); + callout_reset(&sc->vtrnd_callout, 5 * hz, vtrnd_timer, sc); +} diff --git a/sys/sys/random.h b/sys/sys/random.h index d596c7ef6b..8f2f1d6d31 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -77,6 +77,7 @@ #define RAND_SRC_HIFN 0x07 #define RAND_SRC_UBSEC 0x08 #define RAND_SRC_SAFE 0x09 +#define RAND_SRC_VIRTIO 0x0a /* Type of the cookie passed to add_interrupt_randomness. */ -- 2.41.0