master
c 859 lines 27.1 KB
Raw
1 /*
2 * Virtio MMIO bindings
3 *
4 * Copyright (c) 2011 Linaro Limited
5 *
6 * Author:
7 * Peter Maydell <peter.maydell@linaro.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "qemu/osdep.h"
23 #include "standard-headers/linux/virtio_mmio.h"
24 #include "hw/core/irq.h"
25 #include "hw/core/qdev-properties.h"
26 #include "hw/core/sysbus.h"
27 #include "hw/virtio/virtio.h"
28 #include "migration/qemu-file-types.h"
29 #include "qemu/host-utils.h"
30 #include "qemu/module.h"
31 #include "system/kvm.h"
32 #include "system/replay.h"
33 #include "hw/virtio/virtio-mmio.h"
34 #include "qemu/error-report.h"
35 #include "qemu/log.h"
36 #include "trace.h"
37 #include "qapi/error.h"
38
39 static bool virtio_mmio_ioeventfd_enabled(DeviceState *d)
40 {
41 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
42
43 return (proxy->flags & VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD) != 0;
44 }
45
46 static int virtio_mmio_ioeventfd_assign(DeviceState *d,
47 EventNotifier *notifier,
48 int n, bool assign)
49 {
50 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
51
52 if (assign) {
53 memory_region_add_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUE_NOTIFY, 4,
54 true, n, notifier);
55 } else {
56 memory_region_del_eventfd(&proxy->iomem, VIRTIO_MMIO_QUEUE_NOTIFY, 4,
57 true, n, notifier);
58 }
59 return 0;
60 }
61
62 static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
63 {
64 virtio_bus_start_ioeventfd(&proxy->bus);
65 }
66
67 static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
68 {
69 virtio_bus_stop_ioeventfd(&proxy->bus);
70 }
71
72 static void virtio_mmio_soft_reset(VirtIOMMIOProxy *proxy)
73 {
74 int i;
75
76 virtio_bus_reset(&proxy->bus);
77
78 if (!proxy->legacy) {
79 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
80 proxy->vqs[i].enabled = 0;
81 }
82 }
83 }
84
85 static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
86 {
87 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
88 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
89
90 trace_virtio_mmio_read(offset);
91
92 if (!vdev) {
93 /* If no backend is present, we treat most registers as
94 * read-as-zero, except for the magic number, version and
95 * vendor ID. This is not strictly sanctioned by the virtio
96 * spec, but it allows us to provide transports with no backend
97 * plugged in which don't confuse Linux's virtio code: the
98 * probe won't complain about the bad magic number, but the
99 * device ID of zero means no backend will claim it.
100 */
101 switch (offset) {
102 case VIRTIO_MMIO_MAGIC_VALUE:
103 return VIRT_MAGIC;
104 case VIRTIO_MMIO_VERSION:
105 if (proxy->legacy) {
106 return VIRT_VERSION_LEGACY;
107 } else {
108 return VIRT_VERSION;
109 }
110 case VIRTIO_MMIO_VENDOR_ID:
111 return VIRT_VENDOR;
112 default:
113 return 0;
114 }
115 }
116
117 if (offset >= VIRTIO_MMIO_CONFIG) {
118 offset -= VIRTIO_MMIO_CONFIG;
119 if (proxy->legacy) {
120 switch (size) {
121 case 1:
122 return virtio_config_readb(vdev, offset);
123 case 2:
124 return virtio_config_readw(vdev, offset);
125 case 4:
126 return virtio_config_readl(vdev, offset);
127 default:
128 abort();
129 }
130 } else {
131 switch (size) {
132 case 1:
133 return virtio_config_modern_readb(vdev, offset);
134 case 2:
135 return virtio_config_modern_readw(vdev, offset);
136 case 4:
137 return virtio_config_modern_readl(vdev, offset);
138 default:
139 abort();
140 }
141 }
142 }
143 if (size != 4) {
144 qemu_log_mask(LOG_GUEST_ERROR,
145 "%s: wrong size access to register!\n",
146 __func__);
147 return 0;
148 }
149 switch (offset) {
150 case VIRTIO_MMIO_MAGIC_VALUE:
151 return VIRT_MAGIC;
152 case VIRTIO_MMIO_VERSION:
153 if (proxy->legacy) {
154 return VIRT_VERSION_LEGACY;
155 } else {
156 return VIRT_VERSION;
157 }
158 case VIRTIO_MMIO_DEVICE_ID:
159 return vdev->device_id;
160 case VIRTIO_MMIO_VENDOR_ID:
161 return VIRT_VENDOR;
162 case VIRTIO_MMIO_DEVICE_FEATURES:
163 if (proxy->legacy) {
164 if (proxy->host_features_sel) {
165 return 0;
166 } else {
167 return vdev->host_features;
168 }
169 } else {
170 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
171 return (vdev->host_features & ~vdc->legacy_features)
172 >> (32 * proxy->host_features_sel);
173 }
174 case VIRTIO_MMIO_QUEUE_NUM_MAX:
175 return virtio_queue_get_max_num(vdev, vdev->queue_sel);
176 case VIRTIO_MMIO_QUEUE_PFN:
177 if (!proxy->legacy) {
178 qemu_log_mask(LOG_GUEST_ERROR,
179 "%s: read from legacy register (0x%"
180 HWADDR_PRIx ") in non-legacy mode\n",
181 __func__, offset);
182 return 0;
183 }
184 return virtio_queue_get_addr(vdev, vdev->queue_sel)
185 >> proxy->guest_page_shift;
186 case VIRTIO_MMIO_QUEUE_READY:
187 if (proxy->legacy) {
188 qemu_log_mask(LOG_GUEST_ERROR,
189 "%s: read from non-legacy register (0x%"
190 HWADDR_PRIx ") in legacy mode\n",
191 __func__, offset);
192 return 0;
193 }
194 return proxy->vqs[vdev->queue_sel].enabled;
195 case VIRTIO_MMIO_INTERRUPT_STATUS:
196 return qatomic_read(&vdev->isr);
197 case VIRTIO_MMIO_STATUS:
198 return vdev->status;
199 case VIRTIO_MMIO_CONFIG_GENERATION:
200 if (proxy->legacy) {
201 qemu_log_mask(LOG_GUEST_ERROR,
202 "%s: read from non-legacy register (0x%"
203 HWADDR_PRIx ") in legacy mode\n",
204 __func__, offset);
205 return 0;
206 }
207 return vdev->generation;
208 case VIRTIO_MMIO_SHM_LEN_LOW:
209 case VIRTIO_MMIO_SHM_LEN_HIGH:
210 /*
211 * VIRTIO_MMIO_SHM_SEL is unimplemented
212 * according to the linux driver, if region length is -1
213 * the shared memory doesn't exist
214 */
215 return -1;
216 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
217 case VIRTIO_MMIO_DRIVER_FEATURES:
218 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
219 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
220 case VIRTIO_MMIO_QUEUE_SEL:
221 case VIRTIO_MMIO_QUEUE_NUM:
222 case VIRTIO_MMIO_QUEUE_ALIGN:
223 case VIRTIO_MMIO_QUEUE_NOTIFY:
224 case VIRTIO_MMIO_INTERRUPT_ACK:
225 case VIRTIO_MMIO_QUEUE_DESC_LOW:
226 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
227 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
228 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
229 case VIRTIO_MMIO_QUEUE_USED_LOW:
230 case VIRTIO_MMIO_QUEUE_USED_HIGH:
231 qemu_log_mask(LOG_GUEST_ERROR,
232 "%s: read of write-only register (0x%" HWADDR_PRIx ")\n",
233 __func__, offset);
234 return 0;
235 default:
236 qemu_log_mask(LOG_GUEST_ERROR,
237 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
238 __func__, offset);
239 return 0;
240 }
241 return 0;
242 }
243
244 static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
245 unsigned size)
246 {
247 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
248 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
249 uint16_t vq_idx;
250
251 trace_virtio_mmio_write_offset(offset, value);
252
253 if (!vdev) {
254 /* If no backend is present, we just make all registers
255 * write-ignored. This allows us to provide transports with
256 * no backend plugged in.
257 */
258 return;
259 }
260
261 if (offset >= VIRTIO_MMIO_CONFIG) {
262 offset -= VIRTIO_MMIO_CONFIG;
263 if (proxy->legacy) {
264 switch (size) {
265 case 1:
266 virtio_config_writeb(vdev, offset, value);
267 break;
268 case 2:
269 virtio_config_writew(vdev, offset, value);
270 break;
271 case 4:
272 virtio_config_writel(vdev, offset, value);
273 break;
274 default:
275 abort();
276 }
277 return;
278 } else {
279 switch (size) {
280 case 1:
281 virtio_config_modern_writeb(vdev, offset, value);
282 break;
283 case 2:
284 virtio_config_modern_writew(vdev, offset, value);
285 break;
286 case 4:
287 virtio_config_modern_writel(vdev, offset, value);
288 break;
289 default:
290 abort();
291 }
292 return;
293 }
294 }
295 if (size != 4) {
296 qemu_log_mask(LOG_GUEST_ERROR,
297 "%s: wrong size access to register!\n",
298 __func__);
299 return;
300 }
301 switch (offset) {
302 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
303 if (value) {
304 proxy->host_features_sel = 1;
305 } else {
306 proxy->host_features_sel = 0;
307 }
308 break;
309 case VIRTIO_MMIO_DRIVER_FEATURES:
310 if (proxy->legacy) {
311 if (proxy->guest_features_sel) {
312 qemu_log_mask(LOG_GUEST_ERROR,
313 "%s: attempt to write guest features with "
314 "guest_features_sel > 0 in legacy mode\n",
315 __func__);
316 } else {
317 virtio_set_features(vdev, value);
318 }
319 } else {
320 proxy->guest_features[proxy->guest_features_sel] = value;
321 }
322 break;
323 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
324 if (value) {
325 proxy->guest_features_sel = 1;
326 } else {
327 proxy->guest_features_sel = 0;
328 }
329 break;
330 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
331 if (!proxy->legacy) {
332 qemu_log_mask(LOG_GUEST_ERROR,
333 "%s: write to legacy register (0x%"
334 HWADDR_PRIx ") in non-legacy mode\n",
335 __func__, offset);
336 return;
337 }
338 proxy->guest_page_shift = ctz32(value);
339 if (proxy->guest_page_shift > 31) {
340 proxy->guest_page_shift = 0;
341 }
342 trace_virtio_mmio_guest_page(value, proxy->guest_page_shift);
343 break;
344 case VIRTIO_MMIO_QUEUE_SEL:
345 if (value < VIRTIO_QUEUE_MAX) {
346 vdev->queue_sel = value;
347 }
348 break;
349 case VIRTIO_MMIO_QUEUE_NUM:
350 trace_virtio_mmio_queue_write(value, VIRTQUEUE_MAX_SIZE);
351 virtio_queue_set_num(vdev, vdev->queue_sel, value);
352
353 if (proxy->legacy) {
354 virtio_queue_update_rings(vdev, vdev->queue_sel);
355 } else {
356 virtio_init_region_cache(vdev, vdev->queue_sel);
357 proxy->vqs[vdev->queue_sel].num = value;
358 }
359 break;
360 case VIRTIO_MMIO_QUEUE_ALIGN:
361 if (!proxy->legacy) {
362 qemu_log_mask(LOG_GUEST_ERROR,
363 "%s: write to legacy register (0x%"
364 HWADDR_PRIx ") in non-legacy mode\n",
365 __func__, offset);
366 return;
367 }
368 virtio_queue_set_align(vdev, vdev->queue_sel, value);
369 break;
370 case VIRTIO_MMIO_QUEUE_PFN:
371 if (!proxy->legacy) {
372 qemu_log_mask(LOG_GUEST_ERROR,
373 "%s: write to legacy register (0x%"
374 HWADDR_PRIx ") in non-legacy mode\n",
375 __func__, offset);
376 return;
377 }
378 if (value == 0) {
379 virtio_mmio_soft_reset(proxy);
380 } else {
381 virtio_queue_set_addr(vdev, vdev->queue_sel,
382 value << proxy->guest_page_shift);
383 }
384 break;
385 case VIRTIO_MMIO_QUEUE_READY:
386 if (proxy->legacy) {
387 qemu_log_mask(LOG_GUEST_ERROR,
388 "%s: write to non-legacy register (0x%"
389 HWADDR_PRIx ") in legacy mode\n",
390 __func__, offset);
391 return;
392 }
393 if (value) {
394 virtio_queue_set_num(vdev, vdev->queue_sel,
395 proxy->vqs[vdev->queue_sel].num);
396 virtio_queue_set_rings(vdev, vdev->queue_sel,
397 ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 |
398 proxy->vqs[vdev->queue_sel].desc[0],
399 ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 |
400 proxy->vqs[vdev->queue_sel].avail[0],
401 ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
402 proxy->vqs[vdev->queue_sel].used[0]);
403 proxy->vqs[vdev->queue_sel].enabled = 1;
404 } else {
405 proxy->vqs[vdev->queue_sel].enabled = 0;
406 }
407 break;
408 case VIRTIO_MMIO_QUEUE_NOTIFY:
409 vq_idx = value;
410 if (vq_idx < VIRTIO_QUEUE_MAX && virtio_queue_get_num(vdev, vq_idx)) {
411 if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) {
412 VirtQueue *vq = virtio_get_queue(vdev, vq_idx);
413
414 virtio_queue_set_shadow_avail_idx(vq, (value >> 16) & 0xFFFF);
415 }
416 virtio_queue_notify(vdev, vq_idx);
417 }
418 break;
419 case VIRTIO_MMIO_INTERRUPT_ACK:
420 qatomic_and(&vdev->isr, ~value);
421 virtio_update_irq(vdev);
422 break;
423 case VIRTIO_MMIO_STATUS:
424 if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
425 virtio_mmio_stop_ioeventfd(proxy);
426 }
427
428 if (!proxy->legacy && (value & VIRTIO_CONFIG_S_FEATURES_OK)) {
429 virtio_set_features(vdev,
430 ((uint64_t)proxy->guest_features[1]) << 32 |
431 proxy->guest_features[0]);
432 }
433
434 virtio_set_status(vdev, value & 0xff);
435
436 if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
437 virtio_mmio_start_ioeventfd(proxy);
438 }
439
440 if (vdev->status == 0) {
441 virtio_mmio_soft_reset(proxy);
442 }
443 break;
444 case VIRTIO_MMIO_QUEUE_DESC_LOW:
445 if (proxy->legacy) {
446 qemu_log_mask(LOG_GUEST_ERROR,
447 "%s: write to non-legacy register (0x%"
448 HWADDR_PRIx ") in legacy mode\n",
449 __func__, offset);
450 return;
451 }
452 proxy->vqs[vdev->queue_sel].desc[0] = value;
453 break;
454 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
455 if (proxy->legacy) {
456 qemu_log_mask(LOG_GUEST_ERROR,
457 "%s: write to non-legacy register (0x%"
458 HWADDR_PRIx ") in legacy mode\n",
459 __func__, offset);
460 return;
461 }
462 proxy->vqs[vdev->queue_sel].desc[1] = value;
463 break;
464 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
465 if (proxy->legacy) {
466 qemu_log_mask(LOG_GUEST_ERROR,
467 "%s: write to non-legacy register (0x%"
468 HWADDR_PRIx ") in legacy mode\n",
469 __func__, offset);
470 return;
471 }
472 proxy->vqs[vdev->queue_sel].avail[0] = value;
473 break;
474 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
475 if (proxy->legacy) {
476 qemu_log_mask(LOG_GUEST_ERROR,
477 "%s: write to non-legacy register (0x%"
478 HWADDR_PRIx ") in legacy mode\n",
479 __func__, offset);
480 return;
481 }
482 proxy->vqs[vdev->queue_sel].avail[1] = value;
483 break;
484 case VIRTIO_MMIO_QUEUE_USED_LOW:
485 if (proxy->legacy) {
486 qemu_log_mask(LOG_GUEST_ERROR,
487 "%s: write to non-legacy register (0x%"
488 HWADDR_PRIx ") in legacy mode\n",
489 __func__, offset);
490 return;
491 }
492 proxy->vqs[vdev->queue_sel].used[0] = value;
493 break;
494 case VIRTIO_MMIO_QUEUE_USED_HIGH:
495 if (proxy->legacy) {
496 qemu_log_mask(LOG_GUEST_ERROR,
497 "%s: write to non-legacy register (0x%"
498 HWADDR_PRIx ") in legacy mode\n",
499 __func__, offset);
500 return;
501 }
502 proxy->vqs[vdev->queue_sel].used[1] = value;
503 break;
504 case VIRTIO_MMIO_MAGIC_VALUE:
505 case VIRTIO_MMIO_VERSION:
506 case VIRTIO_MMIO_DEVICE_ID:
507 case VIRTIO_MMIO_VENDOR_ID:
508 case VIRTIO_MMIO_DEVICE_FEATURES:
509 case VIRTIO_MMIO_QUEUE_NUM_MAX:
510 case VIRTIO_MMIO_INTERRUPT_STATUS:
511 case VIRTIO_MMIO_CONFIG_GENERATION:
512 qemu_log_mask(LOG_GUEST_ERROR,
513 "%s: write to read-only register (0x%" HWADDR_PRIx ")\n",
514 __func__, offset);
515 break;
516
517 default:
518 qemu_log_mask(LOG_GUEST_ERROR,
519 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
520 __func__, offset);
521 }
522 }
523
524 static const MemoryRegionOps virtio_legacy_mem_ops = {
525 .read = virtio_mmio_read,
526 .write = virtio_mmio_write,
527 .endianness = DEVICE_NATIVE_ENDIAN,
528 };
529
530 static const MemoryRegionOps virtio_mem_ops = {
531 .read = virtio_mmio_read,
532 .write = virtio_mmio_write,
533 .endianness = DEVICE_LITTLE_ENDIAN,
534 };
535
536 static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
537 {
538 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
539 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
540 int level;
541
542 if (!vdev) {
543 return;
544 }
545 level = (qatomic_read(&vdev->isr) != 0);
546 trace_virtio_mmio_setting_irq(level);
547 qemu_set_irq(proxy->irq, level);
548 }
549
550 static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
551 {
552 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
553
554 proxy->host_features_sel = qemu_get_be32(f);
555 proxy->guest_features_sel = qemu_get_be32(f);
556 proxy->guest_page_shift = qemu_get_be32(f);
557 return 0;
558 }
559
560 static void virtio_mmio_save_config(DeviceState *opaque, QEMUFile *f)
561 {
562 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
563
564 qemu_put_be32(f, proxy->host_features_sel);
565 qemu_put_be32(f, proxy->guest_features_sel);
566 qemu_put_be32(f, proxy->guest_page_shift);
567 }
568
569 static const VMStateDescription vmstate_virtio_mmio_queue_state = {
570 .name = "virtio_mmio/queue_state",
571 .version_id = 1,
572 .minimum_version_id = 1,
573 .fields = (const VMStateField[]) {
574 VMSTATE_UINT16(num, VirtIOMMIOQueue),
575 VMSTATE_BOOL(enabled, VirtIOMMIOQueue),
576 VMSTATE_UINT32_ARRAY(desc, VirtIOMMIOQueue, 2),
577 VMSTATE_UINT32_ARRAY(avail, VirtIOMMIOQueue, 2),
578 VMSTATE_UINT32_ARRAY(used, VirtIOMMIOQueue, 2),
579 VMSTATE_END_OF_LIST()
580 }
581 };
582
583 static const VMStateDescription vmstate_virtio_mmio_state_sub = {
584 .name = "virtio_mmio/state",
585 .version_id = 1,
586 .minimum_version_id = 1,
587 .fields = (const VMStateField[]) {
588 VMSTATE_UINT32_ARRAY(guest_features, VirtIOMMIOProxy, 2),
589 VMSTATE_STRUCT_ARRAY(vqs, VirtIOMMIOProxy, VIRTIO_QUEUE_MAX, 0,
590 vmstate_virtio_mmio_queue_state,
591 VirtIOMMIOQueue),
592 VMSTATE_END_OF_LIST()
593 }
594 };
595
596 static const VMStateDescription vmstate_virtio_mmio = {
597 .name = "virtio_mmio",
598 .version_id = 1,
599 .minimum_version_id = 1,
600 .fields = (const VMStateField[]) {
601 VMSTATE_END_OF_LIST()
602 },
603 .subsections = (const VMStateDescription * const []) {
604 &vmstate_virtio_mmio_state_sub,
605 NULL
606 }
607 };
608
609 static void virtio_mmio_save_extra_state(DeviceState *opaque, QEMUFile *f)
610 {
611 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
612 Error *local_err = NULL;
613 int ret;
614
615 ret = vmstate_save_state(f, &vmstate_virtio_mmio, proxy, NULL, &local_err);
616 if (ret < 0) {
617 error_report_err(local_err);
618 }
619 }
620
621 static int virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f)
622 {
623 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
624 Error *local_err = NULL;
625 int ret;
626
627 ret = vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1, &local_err);
628 if (ret < 0) {
629 error_report_err(local_err);
630 }
631 return ret;
632 }
633
634 static bool virtio_mmio_has_extra_state(DeviceState *opaque)
635 {
636 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
637
638 return !proxy->legacy;
639 }
640
641 static void virtio_mmio_reset(DeviceState *d)
642 {
643 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
644 int i;
645
646 virtio_mmio_soft_reset(proxy);
647
648 proxy->host_features_sel = 0;
649 proxy->guest_features_sel = 0;
650 proxy->guest_page_shift = 0;
651
652 if (!proxy->legacy) {
653 proxy->guest_features[0] = proxy->guest_features[1] = 0;
654
655 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
656 proxy->vqs[i].num = 0;
657 proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
658 proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
659 proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0;
660 }
661 }
662 }
663
664 static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
665 bool with_irqfd)
666 {
667 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
668 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
669 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
670 int r;
671
672 r = virtio_set_guest_notifier(vdev, n, assign, with_irqfd);
673 if (r < 0) {
674 return r;
675 }
676
677 if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
678 vdc->guest_notifier_mask(vdev, n, !assign);
679 }
680
681 return 0;
682 }
683
684 static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
685 bool assign)
686 {
687 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
688 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
689 /* TODO: need to check if kvm-arm supports irqfd */
690 bool with_irqfd = false;
691 int r, n;
692
693 nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX);
694
695 for (n = 0; n < nvqs; n++) {
696 if (!virtio_queue_get_num(vdev, n)) {
697 break;
698 }
699
700 r = virtio_mmio_set_guest_notifier(d, n, assign, with_irqfd);
701 if (r < 0) {
702 goto assign_error;
703 }
704 }
705 r = virtio_mmio_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign,
706 with_irqfd);
707 if (r < 0) {
708 goto assign_error;
709 }
710
711 return 0;
712
713 assign_error:
714 /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
715 assert(assign);
716 while (--n >= 0) {
717 virtio_mmio_set_guest_notifier(d, n, !assign, false);
718 }
719 return r;
720 }
721
722 static void virtio_mmio_pre_plugged(DeviceState *d, Error **errp)
723 {
724 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
725 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
726
727 if (!proxy->legacy) {
728 virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
729 }
730 }
731
732 /* virtio-mmio device */
733
734 static const Property virtio_mmio_properties[] = {
735 DEFINE_PROP_BOOL("force-legacy", VirtIOMMIOProxy, legacy, true),
736 DEFINE_PROP_BIT("ioeventfd", VirtIOMMIOProxy, flags,
737 VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD_BIT, true),
738 DEFINE_PROP_UINT16(VIRTIO_QUEUE_SIZE_OVERRIDE, VirtIOMMIOProxy,
739 override_queue_size, 0),
740 };
741
742 static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
743 {
744 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
745 SysBusDevice *sbd = SYS_BUS_DEVICE(d);
746
747 qbus_init(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS, d, NULL);
748 sysbus_init_irq(sbd, &proxy->irq);
749
750 /* fd-based ioevents can't be synchronized in record/replay */
751 if (replay_mode != REPLAY_MODE_NONE) {
752 proxy->flags &= ~VIRTIO_IOMMIO_FLAG_USE_IOEVENTFD;
753 }
754
755 if (proxy->legacy) {
756 memory_region_init_io(&proxy->iomem, OBJECT(d),
757 &virtio_legacy_mem_ops, proxy,
758 TYPE_VIRTIO_MMIO, 0x200);
759 } else {
760 memory_region_init_io(&proxy->iomem, OBJECT(d),
761 &virtio_mem_ops, proxy,
762 TYPE_VIRTIO_MMIO, 0x200);
763 }
764 sysbus_init_mmio(sbd, &proxy->iomem);
765 }
766
767 static void virtio_mmio_class_init(ObjectClass *klass, const void *data)
768 {
769 DeviceClass *dc = DEVICE_CLASS(klass);
770
771 dc->realize = virtio_mmio_realizefn;
772 device_class_set_legacy_reset(dc, virtio_mmio_reset);
773 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
774 device_class_set_props(dc, virtio_mmio_properties);
775 }
776
777 static const TypeInfo virtio_mmio_info = {
778 .name = TYPE_VIRTIO_MMIO,
779 .parent = TYPE_SYS_BUS_DEVICE,
780 .instance_size = sizeof(VirtIOMMIOProxy),
781 .class_init = virtio_mmio_class_init,
782 };
783
784 /* virtio-mmio-bus. */
785
786 static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
787 {
788 BusState *virtio_mmio_bus;
789 VirtIOMMIOProxy *virtio_mmio_proxy;
790 char *proxy_path;
791 char *path;
792 MemoryRegionSection section;
793
794 virtio_mmio_bus = qdev_get_parent_bus(dev);
795 virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
796 proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy));
797
798 section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
799 assert(section.mr);
800
801 if (proxy_path) {
802 path = g_strdup_printf("%s/virtio-mmio@" HWADDR_FMT_plx, proxy_path,
803 section.offset_within_address_space);
804 } else {
805 path = g_strdup_printf("virtio-mmio@" HWADDR_FMT_plx,
806 section.offset_within_address_space);
807 }
808 memory_region_unref(section.mr);
809
810 g_free(proxy_path);
811 return path;
812 }
813
814 static void virtio_mmio_vmstate_change(DeviceState *d, bool running)
815 {
816 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
817
818 if (running) {
819 virtio_mmio_start_ioeventfd(proxy);
820 } else {
821 virtio_mmio_stop_ioeventfd(proxy);
822 }
823 }
824
825 static void virtio_mmio_bus_class_init(ObjectClass *klass, const void *data)
826 {
827 BusClass *bus_class = BUS_CLASS(klass);
828 VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
829
830 k->notify = virtio_mmio_update_irq;
831 k->save_config = virtio_mmio_save_config;
832 k->load_config = virtio_mmio_load_config;
833 k->save_extra_state = virtio_mmio_save_extra_state;
834 k->load_extra_state = virtio_mmio_load_extra_state;
835 k->has_extra_state = virtio_mmio_has_extra_state;
836 k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
837 k->ioeventfd_enabled = virtio_mmio_ioeventfd_enabled;
838 k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
839 k->pre_plugged = virtio_mmio_pre_plugged;
840 k->vmstate_change = virtio_mmio_vmstate_change;
841 k->has_variable_vring_alignment = true;
842 bus_class->max_dev = 1;
843 bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
844 }
845
846 static const TypeInfo virtio_mmio_bus_info = {
847 .name = TYPE_VIRTIO_MMIO_BUS,
848 .parent = TYPE_VIRTIO_BUS,
849 .instance_size = sizeof(VirtioBusState),
850 .class_init = virtio_mmio_bus_class_init,
851 };
852
853 static void virtio_mmio_register_types(void)
854 {
855 type_register_static(&virtio_mmio_bus_info);
856 type_register_static(&virtio_mmio_info);
857 }
858
859 type_init(virtio_mmio_register_types)