]> git.proxmox.com Git - mirror_qemu.git/blob - hw/virtio/virtio-rng.c
62867d141e60e52550ed254d5bd2767c9e765ea8
[mirror_qemu.git] / hw / virtio / virtio-rng.c
1 /*
2 * A virtio device implementing a hardware random number generator.
3 *
4 * Copyright 2012 Red Hat, Inc.
5 * Copyright 2012 Amit Shah <amit.shah@redhat.com>
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * (at your option) any later version. See the COPYING file in the
9 * top-level directory.
10 */
11
12 #define VMSTATE_VIRTIO_DEVICE_USE_NEW
13
14 #include "qemu/osdep.h"
15 #include "qapi/error.h"
16 #include "qemu/iov.h"
17 #include "hw/qdev.h"
18 #include "hw/virtio/virtio.h"
19 #include "hw/virtio/virtio-rng.h"
20 #include "sysemu/rng.h"
21 #include "qom/object_interfaces.h"
22 #include "trace.h"
23
24 static bool is_guest_ready(VirtIORNG *vrng)
25 {
26 VirtIODevice *vdev = VIRTIO_DEVICE(vrng);
27 if (virtio_queue_ready(vrng->vq)
28 && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
29 return true;
30 }
31 trace_virtio_rng_guest_not_ready(vrng);
32 return false;
33 }
34
35 static size_t get_request_size(VirtQueue *vq, unsigned quota)
36 {
37 unsigned int in, out;
38
39 virtqueue_get_avail_bytes(vq, &in, &out, quota, 0);
40 return in;
41 }
42
43 static void virtio_rng_process(VirtIORNG *vrng);
44
45 /* Send data from a char device over to the guest */
46 static void chr_read(void *opaque, const void *buf, size_t size)
47 {
48 VirtIORNG *vrng = opaque;
49 VirtIODevice *vdev = VIRTIO_DEVICE(vrng);
50 VirtQueueElement *elem;
51 size_t len;
52 int offset;
53
54 if (!is_guest_ready(vrng)) {
55 return;
56 }
57
58 vrng->quota_remaining -= size;
59
60 offset = 0;
61 while (offset < size) {
62 elem = virtqueue_pop(vrng->vq, sizeof(VirtQueueElement));
63 if (!elem) {
64 break;
65 }
66 len = iov_from_buf(elem->in_sg, elem->in_num,
67 0, buf + offset, size - offset);
68 offset += len;
69
70 virtqueue_push(vrng->vq, elem, len);
71 trace_virtio_rng_pushed(vrng, len);
72 g_free(elem);
73 }
74 virtio_notify(vdev, vrng->vq);
75
76 if (!virtio_queue_empty(vrng->vq)) {
77 /* If we didn't drain the queue, call virtio_rng_process
78 * to take care of asking for more data as appropriate.
79 */
80 virtio_rng_process(vrng);
81 }
82 }
83
84 static void virtio_rng_process(VirtIORNG *vrng)
85 {
86 size_t size;
87 unsigned quota;
88
89 if (!is_guest_ready(vrng)) {
90 return;
91 }
92
93 if (vrng->activate_timer) {
94 timer_mod(vrng->rate_limit_timer,
95 qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + vrng->conf.period_ms);
96 vrng->activate_timer = false;
97 }
98
99 if (vrng->quota_remaining < 0) {
100 quota = 0;
101 } else {
102 quota = MIN((uint64_t)vrng->quota_remaining, (uint64_t)UINT32_MAX);
103 }
104 size = get_request_size(vrng->vq, quota);
105
106 trace_virtio_rng_request(vrng, size, quota);
107
108 size = MIN(vrng->quota_remaining, size);
109 if (size) {
110 rng_backend_request_entropy(vrng->rng, size, chr_read, vrng);
111 }
112 }
113
114 static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
115 {
116 VirtIORNG *vrng = VIRTIO_RNG(vdev);
117 virtio_rng_process(vrng);
118 }
119
120 static uint64_t get_features(VirtIODevice *vdev, uint64_t f, Error **errp)
121 {
122 return f;
123 }
124
125 static int virtio_rng_post_load(void *opaque, int version_id)
126 {
127 VirtIORNG *vrng = opaque;
128
129 /* We may have an element ready but couldn't process it due to a quota
130 * limit. Make sure to try again after live migration when the quota may
131 * have been reset.
132 */
133 virtio_rng_process(vrng);
134
135 return 0;
136 }
137
138 static void check_rate_limit(void *opaque)
139 {
140 VirtIORNG *vrng = opaque;
141
142 vrng->quota_remaining = vrng->conf.max_bytes;
143 virtio_rng_process(vrng);
144 vrng->activate_timer = true;
145 }
146
147 static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
148 {
149 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
150 VirtIORNG *vrng = VIRTIO_RNG(dev);
151 Error *local_err = NULL;
152
153 if (vrng->conf.period_ms <= 0) {
154 error_setg(errp, "'period' parameter expects a positive integer");
155 return;
156 }
157
158 /* Workaround: Property parsing does not enforce unsigned integers,
159 * So this is a hack to reject such numbers. */
160 if (vrng->conf.max_bytes > INT64_MAX) {
161 error_setg(errp, "'max-bytes' parameter must be non-negative, "
162 "and less than 2^63");
163 return;
164 }
165
166 if (vrng->conf.rng == NULL) {
167 vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
168
169 user_creatable_complete(OBJECT(vrng->conf.default_backend),
170 &local_err);
171 if (local_err) {
172 error_propagate(errp, local_err);
173 object_unref(OBJECT(vrng->conf.default_backend));
174 return;
175 }
176
177 object_property_add_child(OBJECT(dev),
178 "default-backend",
179 OBJECT(vrng->conf.default_backend),
180 NULL);
181
182 /* The child property took a reference, we can safely drop ours now */
183 object_unref(OBJECT(vrng->conf.default_backend));
184
185 object_property_set_link(OBJECT(dev),
186 OBJECT(vrng->conf.default_backend),
187 "rng", NULL);
188 }
189
190 vrng->rng = vrng->conf.rng;
191 if (vrng->rng == NULL) {
192 error_setg(errp, "'rng' parameter expects a valid object");
193 return;
194 }
195
196 virtio_init(vdev, "virtio-rng", VIRTIO_ID_RNG, 0);
197
198 vrng->vq = virtio_add_queue(vdev, 8, handle_input);
199 vrng->quota_remaining = vrng->conf.max_bytes;
200 vrng->rate_limit_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
201 check_rate_limit, vrng);
202 vrng->activate_timer = true;
203 }
204
205 static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp)
206 {
207 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
208 VirtIORNG *vrng = VIRTIO_RNG(dev);
209
210 timer_del(vrng->rate_limit_timer);
211 timer_free(vrng->rate_limit_timer);
212 virtio_cleanup(vdev);
213 }
214
215 static const VMStateDescription vmstate_virtio_rng = {
216 .name = "virtio-rng",
217 .minimum_version_id = 1,
218 .version_id = 1,
219 .fields = (VMStateField[]) {
220 VMSTATE_VIRTIO_DEVICE,
221 VMSTATE_END_OF_LIST()
222 },
223 .post_load = virtio_rng_post_load,
224 };
225
226 static Property virtio_rng_properties[] = {
227 /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If
228 * you have an entropy source capable of generating more entropy than this
229 * and you can pass it through via virtio-rng, then hats off to you. Until
230 * then, this is unlimited for all practical purposes.
231 */
232 DEFINE_PROP_UINT64("max-bytes", VirtIORNG, conf.max_bytes, INT64_MAX),
233 DEFINE_PROP_UINT32("period", VirtIORNG, conf.period_ms, 1 << 16),
234 DEFINE_PROP_END_OF_LIST(),
235 };
236
237 static void virtio_rng_class_init(ObjectClass *klass, void *data)
238 {
239 DeviceClass *dc = DEVICE_CLASS(klass);
240 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
241
242 dc->props = virtio_rng_properties;
243 dc->vmsd = &vmstate_virtio_rng;
244 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
245 vdc->realize = virtio_rng_device_realize;
246 vdc->unrealize = virtio_rng_device_unrealize;
247 vdc->get_features = get_features;
248 }
249
250 static void virtio_rng_initfn(Object *obj)
251 {
252 VirtIORNG *vrng = VIRTIO_RNG(obj);
253
254 object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
255 (Object **)&vrng->conf.rng,
256 qdev_prop_allow_set_link_before_realize,
257 OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
258 }
259
260 static const TypeInfo virtio_rng_info = {
261 .name = TYPE_VIRTIO_RNG,
262 .parent = TYPE_VIRTIO_DEVICE,
263 .instance_size = sizeof(VirtIORNG),
264 .instance_init = virtio_rng_initfn,
265 .class_init = virtio_rng_class_init,
266 };
267
268 static void virtio_register_types(void)
269 {
270 type_register_static(&virtio_rng_info);
271 }
272
273 type_init(virtio_register_types)