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