GNU Linux-libre 5.10.217-gnu1
[releases.git] / drivers / char / hw_random / virtio-rng.c
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 <asm/barrier.h>
8 #include <linux/err.h>
9 #include <linux/hw_random.h>
10 #include <linux/scatterlist.h>
11 #include <linux/spinlock.h>
12 #include <linux/virtio.h>
13 #include <linux/virtio_rng.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16
17 static DEFINE_IDA(rng_index_ida);
18
19 struct virtrng_info {
20         struct hwrng hwrng;
21         struct virtqueue *vq;
22         char name[25];
23         int index;
24         bool hwrng_register_done;
25         bool hwrng_removed;
26         /* data transfer */
27         struct completion have_data;
28         unsigned int data_avail;
29         unsigned int data_idx;
30         /* minimal size returned by rng_buffer_size() */
31 #if SMP_CACHE_BYTES < 32
32         u8 data[32];
33 #else
34         u8 data[SMP_CACHE_BYTES];
35 #endif
36 };
37
38 static void random_recv_done(struct virtqueue *vq)
39 {
40         struct virtrng_info *vi = vq->vdev->priv;
41         unsigned int len;
42
43         /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
44         if (!virtqueue_get_buf(vi->vq, &len))
45                 return;
46
47         smp_store_release(&vi->data_avail, len);
48         complete(&vi->have_data);
49 }
50
51 static void request_entropy(struct virtrng_info *vi)
52 {
53         struct scatterlist sg;
54
55         reinit_completion(&vi->have_data);
56         vi->data_idx = 0;
57
58         sg_init_one(&sg, vi->data, sizeof(vi->data));
59
60         /* There should always be room for one buffer. */
61         virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
62
63         virtqueue_kick(vi->vq);
64 }
65
66 static unsigned int copy_data(struct virtrng_info *vi, void *buf,
67                               unsigned int size)
68 {
69         size = min_t(unsigned int, size, vi->data_avail);
70         memcpy(buf, vi->data + vi->data_idx, size);
71         vi->data_idx += size;
72         vi->data_avail -= size;
73         if (vi->data_avail == 0)
74                 request_entropy(vi);
75         return size;
76 }
77
78 static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
79 {
80         int ret;
81         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
82         unsigned int chunk;
83         size_t read;
84
85         if (vi->hwrng_removed)
86                 return -ENODEV;
87
88         read = 0;
89
90         /* copy available data */
91         if (smp_load_acquire(&vi->data_avail)) {
92                 chunk = copy_data(vi, buf, size);
93                 size -= chunk;
94                 read += chunk;
95         }
96
97         if (!wait)
98                 return read;
99
100         /* We have already copied available entropy,
101          * so either size is 0 or data_avail is 0
102          */
103         while (size != 0) {
104                 /* data_avail is 0 but a request is pending */
105                 ret = wait_for_completion_killable(&vi->have_data);
106                 if (ret < 0)
107                         return ret;
108                 /* if vi->data_avail is 0, we have been interrupted
109                  * by a cleanup, but buffer stays in the queue
110                  */
111                 if (vi->data_avail == 0)
112                         return read;
113
114                 chunk = copy_data(vi, buf + read, size);
115                 size -= chunk;
116                 read += chunk;
117         }
118
119         return read;
120 }
121
122 static void virtio_cleanup(struct hwrng *rng)
123 {
124         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
125
126         complete(&vi->have_data);
127 }
128
129 static int probe_common(struct virtio_device *vdev)
130 {
131         int err, index;
132         struct virtrng_info *vi = NULL;
133
134         vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL);
135         if (!vi)
136                 return -ENOMEM;
137
138         vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL);
139         if (index < 0) {
140                 err = index;
141                 goto err_ida;
142         }
143         sprintf(vi->name, "virtio_rng.%d", index);
144         init_completion(&vi->have_data);
145
146         vi->hwrng = (struct hwrng) {
147                 .read = virtio_read,
148                 .cleanup = virtio_cleanup,
149                 .priv = (unsigned long)vi,
150                 .name = vi->name,
151                 .quality = 1000,
152         };
153         vdev->priv = vi;
154
155         /* We expect a single virtqueue. */
156         vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input");
157         if (IS_ERR(vi->vq)) {
158                 err = PTR_ERR(vi->vq);
159                 goto err_find;
160         }
161
162         /* we always have a pending entropy request */
163         request_entropy(vi);
164
165         return 0;
166
167 err_find:
168         ida_simple_remove(&rng_index_ida, index);
169 err_ida:
170         kfree(vi);
171         return err;
172 }
173
174 static void remove_common(struct virtio_device *vdev)
175 {
176         struct virtrng_info *vi = vdev->priv;
177
178         vi->hwrng_removed = true;
179         vi->data_avail = 0;
180         vi->data_idx = 0;
181         complete(&vi->have_data);
182         vdev->config->reset(vdev);
183         if (vi->hwrng_register_done)
184                 hwrng_unregister(&vi->hwrng);
185         vdev->config->del_vqs(vdev);
186         ida_simple_remove(&rng_index_ida, vi->index);
187         kfree(vi);
188 }
189
190 static int virtrng_probe(struct virtio_device *vdev)
191 {
192         return probe_common(vdev);
193 }
194
195 static void virtrng_remove(struct virtio_device *vdev)
196 {
197         remove_common(vdev);
198 }
199
200 static void virtrng_scan(struct virtio_device *vdev)
201 {
202         struct virtrng_info *vi = vdev->priv;
203         int err;
204
205         err = hwrng_register(&vi->hwrng);
206         if (!err)
207                 vi->hwrng_register_done = true;
208 }
209
210 #ifdef CONFIG_PM_SLEEP
211 static int virtrng_freeze(struct virtio_device *vdev)
212 {
213         remove_common(vdev);
214         return 0;
215 }
216
217 static int virtrng_restore(struct virtio_device *vdev)
218 {
219         int err;
220
221         err = probe_common(vdev);
222         if (!err) {
223                 struct virtrng_info *vi = vdev->priv;
224
225                 /*
226                  * Set hwrng_removed to ensure that virtio_read()
227                  * does not block waiting for data before the
228                  * registration is complete.
229                  */
230                 vi->hwrng_removed = true;
231                 err = hwrng_register(&vi->hwrng);
232                 if (!err) {
233                         vi->hwrng_register_done = true;
234                         vi->hwrng_removed = false;
235                 }
236         }
237
238         return err;
239 }
240 #endif
241
242 static const struct virtio_device_id id_table[] = {
243         { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
244         { 0 },
245 };
246
247 static struct virtio_driver virtio_rng_driver = {
248         .driver.name =  KBUILD_MODNAME,
249         .driver.owner = THIS_MODULE,
250         .id_table =     id_table,
251         .probe =        virtrng_probe,
252         .remove =       virtrng_remove,
253         .scan =         virtrng_scan,
254 #ifdef CONFIG_PM_SLEEP
255         .freeze =       virtrng_freeze,
256         .restore =      virtrng_restore,
257 #endif
258 };
259
260 module_virtio_driver(virtio_rng_driver);
261 MODULE_DEVICE_TABLE(virtio, id_table);
262 MODULE_DESCRIPTION("Virtio random number driver");
263 MODULE_LICENSE("GPL");