Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Randomness driver for virtio
0004  *  Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
0005  */
0006 
0007 #include <linux/err.h>
0008 #include <linux/hw_random.h>
0009 #include <linux/scatterlist.h>
0010 #include <linux/spinlock.h>
0011 #include <linux/virtio.h>
0012 #include <linux/virtio_rng.h>
0013 #include <linux/module.h>
0014 #include <linux/slab.h>
0015 
0016 static DEFINE_IDA(rng_index_ida);
0017 
0018 struct virtrng_info {
0019     struct hwrng hwrng;
0020     struct virtqueue *vq;
0021     char name[25];
0022     int index;
0023     bool hwrng_register_done;
0024     bool hwrng_removed;
0025     /* data transfer */
0026     struct completion have_data;
0027     unsigned int data_avail;
0028     unsigned int data_idx;
0029     /* minimal size returned by rng_buffer_size() */
0030 #if SMP_CACHE_BYTES < 32
0031     u8 data[32];
0032 #else
0033     u8 data[SMP_CACHE_BYTES];
0034 #endif
0035 };
0036 
0037 static void random_recv_done(struct virtqueue *vq)
0038 {
0039     struct virtrng_info *vi = vq->vdev->priv;
0040 
0041     /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
0042     if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
0043         return;
0044 
0045     vi->data_idx = 0;
0046 
0047     complete(&vi->have_data);
0048 }
0049 
0050 static void request_entropy(struct virtrng_info *vi)
0051 {
0052     struct scatterlist sg;
0053 
0054     reinit_completion(&vi->have_data);
0055     vi->data_avail = 0;
0056     vi->data_idx = 0;
0057 
0058     sg_init_one(&sg, vi->data, sizeof(vi->data));
0059 
0060     /* There should always be room for one buffer. */
0061     virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
0062 
0063     virtqueue_kick(vi->vq);
0064 }
0065 
0066 static unsigned int copy_data(struct virtrng_info *vi, void *buf,
0067                   unsigned int size)
0068 {
0069     size = min_t(unsigned int, size, vi->data_avail);
0070     memcpy(buf, vi->data + vi->data_idx, size);
0071     vi->data_idx += size;
0072     vi->data_avail -= size;
0073     if (vi->data_avail == 0)
0074         request_entropy(vi);
0075     return size;
0076 }
0077 
0078 static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
0079 {
0080     int ret;
0081     struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
0082     unsigned int chunk;
0083     size_t read;
0084 
0085     if (vi->hwrng_removed)
0086         return -ENODEV;
0087 
0088     read = 0;
0089 
0090     /* copy available data */
0091     if (vi->data_avail) {
0092         chunk = copy_data(vi, buf, size);
0093         size -= chunk;
0094         read += chunk;
0095     }
0096 
0097     if (!wait)
0098         return read;
0099 
0100     /* We have already copied available entropy,
0101      * so either size is 0 or data_avail is 0
0102      */
0103     while (size != 0) {
0104         /* data_avail is 0 but a request is pending */
0105         ret = wait_for_completion_killable(&vi->have_data);
0106         if (ret < 0)
0107             return ret;
0108         /* if vi->data_avail is 0, we have been interrupted
0109          * by a cleanup, but buffer stays in the queue
0110          */
0111         if (vi->data_avail == 0)
0112             return read;
0113 
0114         chunk = copy_data(vi, buf + read, size);
0115         size -= chunk;
0116         read += chunk;
0117     }
0118 
0119     return read;
0120 }
0121 
0122 static void virtio_cleanup(struct hwrng *rng)
0123 {
0124     struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
0125 
0126     complete(&vi->have_data);
0127 }
0128 
0129 static int probe_common(struct virtio_device *vdev)
0130 {
0131     int err, index;
0132     struct virtrng_info *vi = NULL;
0133 
0134     vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL);
0135     if (!vi)
0136         return -ENOMEM;
0137 
0138     vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL);
0139     if (index < 0) {
0140         err = index;
0141         goto err_ida;
0142     }
0143     sprintf(vi->name, "virtio_rng.%d", index);
0144     init_completion(&vi->have_data);
0145 
0146     vi->hwrng = (struct hwrng) {
0147         .read = virtio_read,
0148         .cleanup = virtio_cleanup,
0149         .priv = (unsigned long)vi,
0150         .name = vi->name,
0151         .quality = 1000,
0152     };
0153     vdev->priv = vi;
0154 
0155     /* We expect a single virtqueue. */
0156     vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input");
0157     if (IS_ERR(vi->vq)) {
0158         err = PTR_ERR(vi->vq);
0159         goto err_find;
0160     }
0161 
0162     virtio_device_ready(vdev);
0163 
0164     /* we always have a pending entropy request */
0165     request_entropy(vi);
0166 
0167     return 0;
0168 
0169 err_find:
0170     ida_simple_remove(&rng_index_ida, index);
0171 err_ida:
0172     kfree(vi);
0173     return err;
0174 }
0175 
0176 static void remove_common(struct virtio_device *vdev)
0177 {
0178     struct virtrng_info *vi = vdev->priv;
0179 
0180     vi->hwrng_removed = true;
0181     vi->data_avail = 0;
0182     vi->data_idx = 0;
0183     complete(&vi->have_data);
0184     if (vi->hwrng_register_done)
0185         hwrng_unregister(&vi->hwrng);
0186     virtio_reset_device(vdev);
0187     vdev->config->del_vqs(vdev);
0188     ida_simple_remove(&rng_index_ida, vi->index);
0189     kfree(vi);
0190 }
0191 
0192 static int virtrng_probe(struct virtio_device *vdev)
0193 {
0194     return probe_common(vdev);
0195 }
0196 
0197 static void virtrng_remove(struct virtio_device *vdev)
0198 {
0199     remove_common(vdev);
0200 }
0201 
0202 static void virtrng_scan(struct virtio_device *vdev)
0203 {
0204     struct virtrng_info *vi = vdev->priv;
0205     int err;
0206 
0207     err = hwrng_register(&vi->hwrng);
0208     if (!err)
0209         vi->hwrng_register_done = true;
0210 }
0211 
0212 #ifdef CONFIG_PM_SLEEP
0213 static int virtrng_freeze(struct virtio_device *vdev)
0214 {
0215     remove_common(vdev);
0216     return 0;
0217 }
0218 
0219 static int virtrng_restore(struct virtio_device *vdev)
0220 {
0221     int err;
0222 
0223     err = probe_common(vdev);
0224     if (!err) {
0225         struct virtrng_info *vi = vdev->priv;
0226 
0227         /*
0228          * Set hwrng_removed to ensure that virtio_read()
0229          * does not block waiting for data before the
0230          * registration is complete.
0231          */
0232         vi->hwrng_removed = true;
0233         err = hwrng_register(&vi->hwrng);
0234         if (!err) {
0235             vi->hwrng_register_done = true;
0236             vi->hwrng_removed = false;
0237         }
0238     }
0239 
0240     return err;
0241 }
0242 #endif
0243 
0244 static const struct virtio_device_id id_table[] = {
0245     { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
0246     { 0 },
0247 };
0248 
0249 static struct virtio_driver virtio_rng_driver = {
0250     .driver.name =  KBUILD_MODNAME,
0251     .driver.owner = THIS_MODULE,
0252     .id_table = id_table,
0253     .probe =    virtrng_probe,
0254     .remove =   virtrng_remove,
0255     .scan =     virtrng_scan,
0256 #ifdef CONFIG_PM_SLEEP
0257     .freeze =   virtrng_freeze,
0258     .restore =  virtrng_restore,
0259 #endif
0260 };
0261 
0262 module_virtio_driver(virtio_rng_driver);
0263 MODULE_DEVICE_TABLE(virtio, id_table);
0264 MODULE_DESCRIPTION("Virtio random number driver");
0265 MODULE_LICENSE("GPL");