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