linux/drivers/char/hw_random/virtio-rng.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Randomness driver for virtio
   4 *  Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
   5 */
   6
   7#include <linux/err.h>
   8#include <linux/hw_random.h>
   9#include <linux/scatterlist.h>
  10#include <linux/spinlock.h>
  11#include <linux/virtio.h>
  12#include <linux/virtio_rng.h>
  13#include <linux/module.h>
  14#include <linux/slab.h>
  15
  16static DEFINE_IDA(rng_index_ida);
  17
  18struct virtrng_info {
  19        struct hwrng hwrng;
  20        struct virtqueue *vq;
  21        struct completion have_data;
  22        char name[25];
  23        unsigned int data_avail;
  24        int index;
  25        bool busy;
  26        bool hwrng_register_done;
  27        bool hwrng_removed;
  28};
  29
  30static void random_recv_done(struct virtqueue *vq)
  31{
  32        struct virtrng_info *vi = vq->vdev->priv;
  33
  34        /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
  35        if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
  36                return;
  37
  38        complete(&vi->have_data);
  39}
  40
  41/* The host will fill any buffer we give it with sweet, sweet randomness. */
  42static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size)
  43{
  44        struct scatterlist sg;
  45
  46        sg_init_one(&sg, buf, size);
  47
  48        /* There should always be room for one buffer. */
  49        virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL);
  50
  51        virtqueue_kick(vi->vq);
  52}
  53
  54static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
  55{
  56        int ret;
  57        struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
  58
  59        if (vi->hwrng_removed)
  60                return -ENODEV;
  61
  62        if (!vi->busy) {
  63                vi->busy = true;
  64                reinit_completion(&vi->have_data);
  65                register_buffer(vi, buf, size);
  66        }
  67
  68        if (!wait)
  69                return 0;
  70
  71        ret = wait_for_completion_killable(&vi->have_data);
  72        if (ret < 0)
  73                return ret;
  74
  75        vi->busy = false;
  76
  77        return vi->data_avail;
  78}
  79
  80static void virtio_cleanup(struct hwrng *rng)
  81{
  82        struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
  83
  84        if (vi->busy)
  85                wait_for_completion(&vi->have_data);
  86}
  87
  88static int probe_common(struct virtio_device *vdev)
  89{
  90        int err, index;
  91        struct virtrng_info *vi = NULL;
  92
  93        vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL);
  94        if (!vi)
  95                return -ENOMEM;
  96
  97        vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL);
  98        if (index < 0) {
  99                err = index;
 100                goto err_ida;
 101        }
 102        sprintf(vi->name, "virtio_rng.%d", index);
 103        init_completion(&vi->have_data);
 104
 105        vi->hwrng = (struct hwrng) {
 106                .read = virtio_read,
 107                .cleanup = virtio_cleanup,
 108                .priv = (unsigned long)vi,
 109                .name = vi->name,
 110                .quality = 1000,
 111        };
 112        vdev->priv = vi;
 113
 114        /* We expect a single virtqueue. */
 115        vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input");
 116        if (IS_ERR(vi->vq)) {
 117                err = PTR_ERR(vi->vq);
 118                goto err_find;
 119        }
 120
 121        return 0;
 122
 123err_find:
 124        ida_simple_remove(&rng_index_ida, index);
 125err_ida:
 126        kfree(vi);
 127        return err;
 128}
 129
 130static void remove_common(struct virtio_device *vdev)
 131{
 132        struct virtrng_info *vi = vdev->priv;
 133
 134        vi->hwrng_removed = true;
 135        vi->data_avail = 0;
 136        complete(&vi->have_data);
 137        vdev->config->reset(vdev);
 138        vi->busy = false;
 139        if (vi->hwrng_register_done)
 140                hwrng_unregister(&vi->hwrng);
 141        vdev->config->del_vqs(vdev);
 142        ida_simple_remove(&rng_index_ida, vi->index);
 143        kfree(vi);
 144}
 145
 146static int virtrng_probe(struct virtio_device *vdev)
 147{
 148        return probe_common(vdev);
 149}
 150
 151static void virtrng_remove(struct virtio_device *vdev)
 152{
 153        remove_common(vdev);
 154}
 155
 156static void virtrng_scan(struct virtio_device *vdev)
 157{
 158        struct virtrng_info *vi = vdev->priv;
 159        int err;
 160
 161        err = hwrng_register(&vi->hwrng);
 162        if (!err)
 163                vi->hwrng_register_done = true;
 164}
 165
 166#ifdef CONFIG_PM_SLEEP
 167static int virtrng_freeze(struct virtio_device *vdev)
 168{
 169        remove_common(vdev);
 170        return 0;
 171}
 172
 173static int virtrng_restore(struct virtio_device *vdev)
 174{
 175        int err;
 176
 177        err = probe_common(vdev);
 178        if (!err) {
 179                struct virtrng_info *vi = vdev->priv;
 180
 181                /*
 182                 * Set hwrng_removed to ensure that virtio_read()
 183                 * does not block waiting for data before the
 184                 * registration is complete.
 185                 */
 186                vi->hwrng_removed = true;
 187                err = hwrng_register(&vi->hwrng);
 188                if (!err) {
 189                        vi->hwrng_register_done = true;
 190                        vi->hwrng_removed = false;
 191                }
 192        }
 193
 194        return err;
 195}
 196#endif
 197
 198static const struct virtio_device_id id_table[] = {
 199        { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
 200        { 0 },
 201};
 202
 203static struct virtio_driver virtio_rng_driver = {
 204        .driver.name =  KBUILD_MODNAME,
 205        .driver.owner = THIS_MODULE,
 206        .id_table =     id_table,
 207        .probe =        virtrng_probe,
 208        .remove =       virtrng_remove,
 209        .scan =         virtrng_scan,
 210#ifdef CONFIG_PM_SLEEP
 211        .freeze =       virtrng_freeze,
 212        .restore =      virtrng_restore,
 213#endif
 214};
 215
 216module_virtio_driver(virtio_rng_driver);
 217MODULE_DEVICE_TABLE(virtio, id_table);
 218MODULE_DESCRIPTION("Virtio random number driver");
 219MODULE_LICENSE("GPL");
 220