LCOV - code coverage report
Current view: top level - drivers/char/hw_random - virtio-rng.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 1 77 1.3 %
Date: 2021-04-22 12:43:58 Functions: 1 11 9.1 %

          Line data    Source code
       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             : 
      16             : static DEFINE_IDA(rng_index_ida);
      17             : 
      18             : struct 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             : 
      30           0 : static void random_recv_done(struct virtqueue *vq)
      31             : {
      32           0 :         struct virtrng_info *vi = vq->vdev->priv;
      33             : 
      34             :         /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
      35           0 :         if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
      36             :                 return;
      37             : 
      38           0 :         complete(&vi->have_data);
      39             : }
      40             : 
      41             : /* The host will fill any buffer we give it with sweet, sweet randomness. */
      42           0 : static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size)
      43             : {
      44           0 :         struct scatterlist sg;
      45             : 
      46           0 :         sg_init_one(&sg, buf, size);
      47             : 
      48             :         /* There should always be room for one buffer. */
      49           0 :         virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL);
      50             : 
      51           0 :         virtqueue_kick(vi->vq);
      52           0 : }
      53             : 
      54           0 : static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
      55             : {
      56           0 :         int ret;
      57           0 :         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
      58             : 
      59           0 :         if (vi->hwrng_removed)
      60             :                 return -ENODEV;
      61             : 
      62           0 :         if (!vi->busy) {
      63           0 :                 vi->busy = true;
      64           0 :                 reinit_completion(&vi->have_data);
      65           0 :                 register_buffer(vi, buf, size);
      66             :         }
      67             : 
      68           0 :         if (!wait)
      69             :                 return 0;
      70             : 
      71           0 :         ret = wait_for_completion_killable(&vi->have_data);
      72           0 :         if (ret < 0)
      73             :                 return ret;
      74             : 
      75           0 :         vi->busy = false;
      76             : 
      77           0 :         return vi->data_avail;
      78             : }
      79             : 
      80           0 : static void virtio_cleanup(struct hwrng *rng)
      81             : {
      82           0 :         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
      83             : 
      84           0 :         if (vi->busy)
      85           0 :                 wait_for_completion(&vi->have_data);
      86           0 : }
      87             : 
      88           0 : static int probe_common(struct virtio_device *vdev)
      89             : {
      90           0 :         int err, index;
      91           0 :         struct virtrng_info *vi = NULL;
      92             : 
      93           0 :         vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL);
      94           0 :         if (!vi)
      95             :                 return -ENOMEM;
      96             : 
      97           0 :         vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL);
      98           0 :         if (index < 0) {
      99           0 :                 err = index;
     100           0 :                 goto err_ida;
     101             :         }
     102           0 :         sprintf(vi->name, "virtio_rng.%d", index);
     103           0 :         init_completion(&vi->have_data);
     104             : 
     105           0 :         vi->hwrng = (struct hwrng) {
     106             :                 .read = virtio_read,
     107             :                 .cleanup = virtio_cleanup,
     108           0 :                 .priv = (unsigned long)vi,
     109             :                 .name = vi->name,
     110             :                 .quality = 1000,
     111             :         };
     112           0 :         vdev->priv = vi;
     113             : 
     114             :         /* We expect a single virtqueue. */
     115           0 :         vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input");
     116           0 :         if (IS_ERR(vi->vq)) {
     117           0 :                 err = PTR_ERR(vi->vq);
     118           0 :                 goto err_find;
     119             :         }
     120             : 
     121             :         return 0;
     122             : 
     123           0 : err_find:
     124           0 :         ida_simple_remove(&rng_index_ida, index);
     125           0 : err_ida:
     126           0 :         kfree(vi);
     127           0 :         return err;
     128             : }
     129             : 
     130           0 : static void remove_common(struct virtio_device *vdev)
     131             : {
     132           0 :         struct virtrng_info *vi = vdev->priv;
     133             : 
     134           0 :         vi->hwrng_removed = true;
     135           0 :         vi->data_avail = 0;
     136           0 :         complete(&vi->have_data);
     137           0 :         vdev->config->reset(vdev);
     138           0 :         vi->busy = false;
     139           0 :         if (vi->hwrng_register_done)
     140           0 :                 hwrng_unregister(&vi->hwrng);
     141           0 :         vdev->config->del_vqs(vdev);
     142           0 :         ida_simple_remove(&rng_index_ida, vi->index);
     143           0 :         kfree(vi);
     144           0 : }
     145             : 
     146           0 : static int virtrng_probe(struct virtio_device *vdev)
     147             : {
     148           0 :         return probe_common(vdev);
     149             : }
     150             : 
     151           0 : static void virtrng_remove(struct virtio_device *vdev)
     152             : {
     153           0 :         remove_common(vdev);
     154           0 : }
     155             : 
     156           0 : static void virtrng_scan(struct virtio_device *vdev)
     157             : {
     158           0 :         struct virtrng_info *vi = vdev->priv;
     159           0 :         int err;
     160             : 
     161           0 :         err = hwrng_register(&vi->hwrng);
     162           0 :         if (!err)
     163           0 :                 vi->hwrng_register_done = true;
     164           0 : }
     165             : 
     166             : #ifdef CONFIG_PM_SLEEP
     167             : static int virtrng_freeze(struct virtio_device *vdev)
     168             : {
     169             :         remove_common(vdev);
     170             :         return 0;
     171             : }
     172             : 
     173             : static 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             : 
     198             : static const struct virtio_device_id id_table[] = {
     199             :         { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
     200             :         { 0 },
     201             : };
     202             : 
     203             : static 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             : 
     216           1 : module_virtio_driver(virtio_rng_driver);
     217             : MODULE_DEVICE_TABLE(virtio, id_table);
     218             : MODULE_DESCRIPTION("Virtio random number driver");
     219             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14