exec/memory: Use struct Object typedef
[qemu/ar7.git] / hw / virtio / virtio-mmio.c
blob6990b9879cf0ff0cef1176e0a32e9201900451f6
1 /*
2 * Virtio MMIO bindings
4 * Copyright (c) 2011 Linaro Limited
6 * Author:
7 * Peter Maydell <peter.maydell@linaro.org>
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.
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.
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/>.
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"
37 static bool virtio_mmio_ioeventfd_enabled(DeviceState *d)
39 return kvm_eventfds_enabled();
42 static int virtio_mmio_ioeventfd_assign(DeviceState *d,
43 EventNotifier *notifier,
44 int n, bool assign)
46 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
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);
55 return 0;
58 static void virtio_mmio_start_ioeventfd(VirtIOMMIOProxy *proxy)
60 virtio_bus_start_ioeventfd(&proxy->bus);
63 static void virtio_mmio_stop_ioeventfd(VirtIOMMIOProxy *proxy)
65 virtio_bus_stop_ioeventfd(&proxy->bus);
68 static void virtio_mmio_soft_reset(VirtIOMMIOProxy *proxy)
70 int i;
72 if (proxy->legacy) {
73 return;
76 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
77 proxy->vqs[i].enabled = 0;
81 static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
83 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
84 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
86 trace_virtio_mmio_read(offset);
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.
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;
106 case VIRTIO_MMIO_VENDOR_ID:
107 return VIRT_VENDOR;
108 default:
109 return 0;
113 if (offset >= VIRTIO_MMIO_CONFIG) {
114 offset -= VIRTIO_MMIO_CONFIG;
115 switch (size) {
116 case 1:
117 return virtio_config_readb(vdev, offset);
118 case 2:
119 return virtio_config_readw(vdev, offset);
120 case 4:
121 return virtio_config_readl(vdev, offset);
122 default:
123 abort();
126 if (size != 4) {
127 qemu_log_mask(LOG_GUEST_ERROR,
128 "%s: wrong size access to register!\n",
129 __func__);
130 return 0;
132 switch (offset) {
133 case VIRTIO_MMIO_MAGIC_VALUE:
134 return VIRT_MAGIC;
135 case VIRTIO_MMIO_VERSION:
136 if (proxy->legacy) {
137 return VIRT_VERSION_LEGACY;
138 } else {
139 return VIRT_VERSION;
141 case VIRTIO_MMIO_DEVICE_ID:
142 return vdev->device_id;
143 case VIRTIO_MMIO_VENDOR_ID:
144 return VIRT_VENDOR;
145 case VIRTIO_MMIO_DEVICE_FEATURES:
146 if (proxy->legacy) {
147 if (proxy->host_features_sel) {
148 return 0;
149 } else {
150 return vdev->host_features;
152 } else {
153 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
154 return (vdev->host_features & ~vdc->legacy_features)
155 >> (32 * proxy->host_features_sel);
157 case VIRTIO_MMIO_QUEUE_NUM_MAX:
158 if (!virtio_queue_get_num(vdev, vdev->queue_sel)) {
159 return 0;
161 return VIRTQUEUE_MAX_SIZE;
162 case VIRTIO_MMIO_QUEUE_PFN:
163 if (!proxy->legacy) {
164 qemu_log_mask(LOG_GUEST_ERROR,
165 "%s: read from legacy register (0x%"
166 HWADDR_PRIx ") in non-legacy mode\n",
167 __func__, offset);
168 return 0;
170 return virtio_queue_get_addr(vdev, vdev->queue_sel)
171 >> proxy->guest_page_shift;
172 case VIRTIO_MMIO_QUEUE_READY:
173 if (proxy->legacy) {
174 qemu_log_mask(LOG_GUEST_ERROR,
175 "%s: read from non-legacy register (0x%"
176 HWADDR_PRIx ") in legacy mode\n",
177 __func__, offset);
178 return 0;
180 return proxy->vqs[vdev->queue_sel].enabled;
181 case VIRTIO_MMIO_INTERRUPT_STATUS:
182 return qatomic_read(&vdev->isr);
183 case VIRTIO_MMIO_STATUS:
184 return vdev->status;
185 case VIRTIO_MMIO_CONFIG_GENERATION:
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;
193 return vdev->generation;
194 case VIRTIO_MMIO_SHM_LEN_LOW:
195 case VIRTIO_MMIO_SHM_LEN_HIGH:
197 * VIRTIO_MMIO_SHM_SEL is unimplemented
198 * according to the linux driver, if region length is -1
199 * the shared memory doesn't exist
201 return -1;
202 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
203 case VIRTIO_MMIO_DRIVER_FEATURES:
204 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
205 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
206 case VIRTIO_MMIO_QUEUE_SEL:
207 case VIRTIO_MMIO_QUEUE_NUM:
208 case VIRTIO_MMIO_QUEUE_ALIGN:
209 case VIRTIO_MMIO_QUEUE_NOTIFY:
210 case VIRTIO_MMIO_INTERRUPT_ACK:
211 case VIRTIO_MMIO_QUEUE_DESC_LOW:
212 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
213 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
214 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
215 case VIRTIO_MMIO_QUEUE_USED_LOW:
216 case VIRTIO_MMIO_QUEUE_USED_HIGH:
217 qemu_log_mask(LOG_GUEST_ERROR,
218 "%s: read of write-only register (0x%" HWADDR_PRIx ")\n",
219 __func__, offset);
220 return 0;
221 default:
222 qemu_log_mask(LOG_GUEST_ERROR,
223 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
224 __func__, offset);
225 return 0;
227 return 0;
230 static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
231 unsigned size)
233 VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque;
234 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
236 trace_virtio_mmio_write_offset(offset, value);
238 if (!vdev) {
239 /* If no backend is present, we just make all registers
240 * write-ignored. This allows us to provide transports with
241 * no backend plugged in.
243 return;
246 if (offset >= VIRTIO_MMIO_CONFIG) {
247 offset -= VIRTIO_MMIO_CONFIG;
248 switch (size) {
249 case 1:
250 virtio_config_writeb(vdev, offset, value);
251 break;
252 case 2:
253 virtio_config_writew(vdev, offset, value);
254 break;
255 case 4:
256 virtio_config_writel(vdev, offset, value);
257 break;
258 default:
259 abort();
261 return;
263 if (size != 4) {
264 qemu_log_mask(LOG_GUEST_ERROR,
265 "%s: wrong size access to register!\n",
266 __func__);
267 return;
269 switch (offset) {
270 case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
271 if (value) {
272 proxy->host_features_sel = 1;
273 } else {
274 proxy->host_features_sel = 0;
276 break;
277 case VIRTIO_MMIO_DRIVER_FEATURES:
278 if (proxy->legacy) {
279 if (proxy->guest_features_sel) {
280 qemu_log_mask(LOG_GUEST_ERROR,
281 "%s: attempt to write guest features with "
282 "guest_features_sel > 0 in legacy mode\n",
283 __func__);
284 } else {
285 virtio_set_features(vdev, value);
287 } else {
288 proxy->guest_features[proxy->guest_features_sel] = value;
290 break;
291 case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
292 if (value) {
293 proxy->guest_features_sel = 1;
294 } else {
295 proxy->guest_features_sel = 0;
297 break;
298 case VIRTIO_MMIO_GUEST_PAGE_SIZE:
299 if (!proxy->legacy) {
300 qemu_log_mask(LOG_GUEST_ERROR,
301 "%s: write to legacy register (0x%"
302 HWADDR_PRIx ") in non-legacy mode\n",
303 __func__, offset);
304 return;
306 proxy->guest_page_shift = ctz32(value);
307 if (proxy->guest_page_shift > 31) {
308 proxy->guest_page_shift = 0;
310 trace_virtio_mmio_guest_page(value, proxy->guest_page_shift);
311 break;
312 case VIRTIO_MMIO_QUEUE_SEL:
313 if (value < VIRTIO_QUEUE_MAX) {
314 vdev->queue_sel = value;
316 break;
317 case VIRTIO_MMIO_QUEUE_NUM:
318 trace_virtio_mmio_queue_write(value, VIRTQUEUE_MAX_SIZE);
319 virtio_queue_set_num(vdev, vdev->queue_sel, value);
321 if (proxy->legacy) {
322 virtio_queue_update_rings(vdev, vdev->queue_sel);
323 } else {
324 proxy->vqs[vdev->queue_sel].num = value;
326 break;
327 case VIRTIO_MMIO_QUEUE_ALIGN:
328 if (!proxy->legacy) {
329 qemu_log_mask(LOG_GUEST_ERROR,
330 "%s: write to legacy register (0x%"
331 HWADDR_PRIx ") in non-legacy mode\n",
332 __func__, offset);
333 return;
335 virtio_queue_set_align(vdev, vdev->queue_sel, value);
336 break;
337 case VIRTIO_MMIO_QUEUE_PFN:
338 if (!proxy->legacy) {
339 qemu_log_mask(LOG_GUEST_ERROR,
340 "%s: write to legacy register (0x%"
341 HWADDR_PRIx ") in non-legacy mode\n",
342 __func__, offset);
343 return;
345 if (value == 0) {
346 virtio_reset(vdev);
347 } else {
348 virtio_queue_set_addr(vdev, vdev->queue_sel,
349 value << proxy->guest_page_shift);
351 break;
352 case VIRTIO_MMIO_QUEUE_READY:
353 if (proxy->legacy) {
354 qemu_log_mask(LOG_GUEST_ERROR,
355 "%s: write to non-legacy register (0x%"
356 HWADDR_PRIx ") in legacy mode\n",
357 __func__, offset);
358 return;
360 if (value) {
361 virtio_queue_set_num(vdev, vdev->queue_sel,
362 proxy->vqs[vdev->queue_sel].num);
363 virtio_queue_set_rings(vdev, vdev->queue_sel,
364 ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 |
365 proxy->vqs[vdev->queue_sel].desc[0],
366 ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 |
367 proxy->vqs[vdev->queue_sel].avail[0],
368 ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 |
369 proxy->vqs[vdev->queue_sel].used[0]);
370 proxy->vqs[vdev->queue_sel].enabled = 1;
371 } else {
372 proxy->vqs[vdev->queue_sel].enabled = 0;
374 break;
375 case VIRTIO_MMIO_QUEUE_NOTIFY:
376 if (value < VIRTIO_QUEUE_MAX) {
377 virtio_queue_notify(vdev, value);
379 break;
380 case VIRTIO_MMIO_INTERRUPT_ACK:
381 qatomic_and(&vdev->isr, ~value);
382 virtio_update_irq(vdev);
383 break;
384 case VIRTIO_MMIO_STATUS:
385 if (!(value & VIRTIO_CONFIG_S_DRIVER_OK)) {
386 virtio_mmio_stop_ioeventfd(proxy);
389 if (!proxy->legacy && (value & VIRTIO_CONFIG_S_FEATURES_OK)) {
390 virtio_set_features(vdev,
391 ((uint64_t)proxy->guest_features[1]) << 32 |
392 proxy->guest_features[0]);
395 virtio_set_status(vdev, value & 0xff);
397 if (value & VIRTIO_CONFIG_S_DRIVER_OK) {
398 virtio_mmio_start_ioeventfd(proxy);
401 if (vdev->status == 0) {
402 virtio_reset(vdev);
403 virtio_mmio_soft_reset(proxy);
405 break;
406 case VIRTIO_MMIO_QUEUE_DESC_LOW:
407 if (proxy->legacy) {
408 qemu_log_mask(LOG_GUEST_ERROR,
409 "%s: write to non-legacy register (0x%"
410 HWADDR_PRIx ") in legacy mode\n",
411 __func__, offset);
412 return;
414 proxy->vqs[vdev->queue_sel].desc[0] = value;
415 break;
416 case VIRTIO_MMIO_QUEUE_DESC_HIGH:
417 if (proxy->legacy) {
418 qemu_log_mask(LOG_GUEST_ERROR,
419 "%s: write to non-legacy register (0x%"
420 HWADDR_PRIx ") in legacy mode\n",
421 __func__, offset);
422 return;
424 proxy->vqs[vdev->queue_sel].desc[1] = value;
425 break;
426 case VIRTIO_MMIO_QUEUE_AVAIL_LOW:
427 if (proxy->legacy) {
428 qemu_log_mask(LOG_GUEST_ERROR,
429 "%s: write to non-legacy register (0x%"
430 HWADDR_PRIx ") in legacy mode\n",
431 __func__, offset);
432 return;
434 proxy->vqs[vdev->queue_sel].avail[0] = value;
435 break;
436 case VIRTIO_MMIO_QUEUE_AVAIL_HIGH:
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;
444 proxy->vqs[vdev->queue_sel].avail[1] = value;
445 break;
446 case VIRTIO_MMIO_QUEUE_USED_LOW:
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;
454 proxy->vqs[vdev->queue_sel].used[0] = value;
455 break;
456 case VIRTIO_MMIO_QUEUE_USED_HIGH:
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;
464 proxy->vqs[vdev->queue_sel].used[1] = value;
465 break;
466 case VIRTIO_MMIO_MAGIC_VALUE:
467 case VIRTIO_MMIO_VERSION:
468 case VIRTIO_MMIO_DEVICE_ID:
469 case VIRTIO_MMIO_VENDOR_ID:
470 case VIRTIO_MMIO_DEVICE_FEATURES:
471 case VIRTIO_MMIO_QUEUE_NUM_MAX:
472 case VIRTIO_MMIO_INTERRUPT_STATUS:
473 case VIRTIO_MMIO_CONFIG_GENERATION:
474 qemu_log_mask(LOG_GUEST_ERROR,
475 "%s: write to read-only register (0x%" HWADDR_PRIx ")\n",
476 __func__, offset);
477 break;
479 default:
480 qemu_log_mask(LOG_GUEST_ERROR,
481 "%s: bad register offset (0x%" HWADDR_PRIx ")\n",
482 __func__, offset);
486 static const MemoryRegionOps virtio_legacy_mem_ops = {
487 .read = virtio_mmio_read,
488 .write = virtio_mmio_write,
489 .endianness = DEVICE_NATIVE_ENDIAN,
492 static const MemoryRegionOps virtio_mem_ops = {
493 .read = virtio_mmio_read,
494 .write = virtio_mmio_write,
495 .endianness = DEVICE_LITTLE_ENDIAN,
498 static void virtio_mmio_update_irq(DeviceState *opaque, uint16_t vector)
500 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
501 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
502 int level;
504 if (!vdev) {
505 return;
507 level = (qatomic_read(&vdev->isr) != 0);
508 trace_virtio_mmio_setting_irq(level);
509 qemu_set_irq(proxy->irq, level);
512 static int virtio_mmio_load_config(DeviceState *opaque, QEMUFile *f)
514 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
516 proxy->host_features_sel = qemu_get_be32(f);
517 proxy->guest_features_sel = qemu_get_be32(f);
518 proxy->guest_page_shift = qemu_get_be32(f);
519 return 0;
522 static void virtio_mmio_save_config(DeviceState *opaque, QEMUFile *f)
524 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
526 qemu_put_be32(f, proxy->host_features_sel);
527 qemu_put_be32(f, proxy->guest_features_sel);
528 qemu_put_be32(f, proxy->guest_page_shift);
531 static const VMStateDescription vmstate_virtio_mmio_queue_state = {
532 .name = "virtio_mmio/queue_state",
533 .version_id = 1,
534 .minimum_version_id = 1,
535 .fields = (VMStateField[]) {
536 VMSTATE_UINT16(num, VirtIOMMIOQueue),
537 VMSTATE_BOOL(enabled, VirtIOMMIOQueue),
538 VMSTATE_UINT32_ARRAY(desc, VirtIOMMIOQueue, 2),
539 VMSTATE_UINT32_ARRAY(avail, VirtIOMMIOQueue, 2),
540 VMSTATE_UINT32_ARRAY(used, VirtIOMMIOQueue, 2),
541 VMSTATE_END_OF_LIST()
545 static const VMStateDescription vmstate_virtio_mmio_state_sub = {
546 .name = "virtio_mmio/state",
547 .version_id = 1,
548 .minimum_version_id = 1,
549 .fields = (VMStateField[]) {
550 VMSTATE_UINT32_ARRAY(guest_features, VirtIOMMIOProxy, 2),
551 VMSTATE_STRUCT_ARRAY(vqs, VirtIOMMIOProxy, VIRTIO_QUEUE_MAX, 0,
552 vmstate_virtio_mmio_queue_state,
553 VirtIOMMIOQueue),
554 VMSTATE_END_OF_LIST()
558 static const VMStateDescription vmstate_virtio_mmio = {
559 .name = "virtio_mmio",
560 .version_id = 1,
561 .minimum_version_id = 1,
562 .minimum_version_id_old = 1,
563 .fields = (VMStateField[]) {
564 VMSTATE_END_OF_LIST()
566 .subsections = (const VMStateDescription * []) {
567 &vmstate_virtio_mmio_state_sub,
568 NULL
572 static void virtio_mmio_save_extra_state(DeviceState *opaque, QEMUFile *f)
574 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
576 vmstate_save_state(f, &vmstate_virtio_mmio, proxy, NULL);
579 static int virtio_mmio_load_extra_state(DeviceState *opaque, QEMUFile *f)
581 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
583 return vmstate_load_state(f, &vmstate_virtio_mmio, proxy, 1);
586 static bool virtio_mmio_has_extra_state(DeviceState *opaque)
588 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(opaque);
590 return !proxy->legacy;
593 static void virtio_mmio_reset(DeviceState *d)
595 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
596 int i;
598 virtio_mmio_stop_ioeventfd(proxy);
599 virtio_bus_reset(&proxy->bus);
600 proxy->host_features_sel = 0;
601 proxy->guest_features_sel = 0;
602 proxy->guest_page_shift = 0;
604 if (!proxy->legacy) {
605 proxy->guest_features[0] = proxy->guest_features[1] = 0;
607 for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
608 proxy->vqs[i].enabled = 0;
609 proxy->vqs[i].num = 0;
610 proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0;
611 proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0;
612 proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0;
617 static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign,
618 bool with_irqfd)
620 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
621 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
622 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
623 VirtQueue *vq = virtio_get_queue(vdev, n);
624 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
626 if (assign) {
627 int r = event_notifier_init(notifier, 0);
628 if (r < 0) {
629 return r;
631 virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
632 } else {
633 virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
634 event_notifier_cleanup(notifier);
637 if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) {
638 vdc->guest_notifier_mask(vdev, n, !assign);
641 return 0;
644 static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs,
645 bool assign)
647 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
648 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
649 /* TODO: need to check if kvm-arm supports irqfd */
650 bool with_irqfd = false;
651 int r, n;
653 nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX);
655 for (n = 0; n < nvqs; n++) {
656 if (!virtio_queue_get_num(vdev, n)) {
657 break;
660 r = virtio_mmio_set_guest_notifier(d, n, assign, with_irqfd);
661 if (r < 0) {
662 goto assign_error;
666 return 0;
668 assign_error:
669 /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */
670 assert(assign);
671 while (--n >= 0) {
672 virtio_mmio_set_guest_notifier(d, n, !assign, false);
674 return r;
677 static void virtio_mmio_pre_plugged(DeviceState *d, Error **errp)
679 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
680 VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
682 if (!proxy->legacy) {
683 virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
687 /* virtio-mmio device */
689 static Property virtio_mmio_properties[] = {
690 DEFINE_PROP_BOOL("format_transport_address", VirtIOMMIOProxy,
691 format_transport_address, true),
692 DEFINE_PROP_BOOL("force-legacy", VirtIOMMIOProxy, legacy, true),
693 DEFINE_PROP_END_OF_LIST(),
696 static void virtio_mmio_realizefn(DeviceState *d, Error **errp)
698 VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d);
699 SysBusDevice *sbd = SYS_BUS_DEVICE(d);
701 qbus_create_inplace(&proxy->bus, sizeof(proxy->bus), TYPE_VIRTIO_MMIO_BUS,
702 d, NULL);
703 sysbus_init_irq(sbd, &proxy->irq);
704 if (proxy->legacy) {
705 memory_region_init_io(&proxy->iomem, OBJECT(d),
706 &virtio_legacy_mem_ops, proxy,
707 TYPE_VIRTIO_MMIO, 0x200);
708 } else {
709 memory_region_init_io(&proxy->iomem, OBJECT(d),
710 &virtio_mem_ops, proxy,
711 TYPE_VIRTIO_MMIO, 0x200);
713 sysbus_init_mmio(sbd, &proxy->iomem);
716 static void virtio_mmio_class_init(ObjectClass *klass, void *data)
718 DeviceClass *dc = DEVICE_CLASS(klass);
720 dc->realize = virtio_mmio_realizefn;
721 dc->reset = virtio_mmio_reset;
722 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
723 device_class_set_props(dc, virtio_mmio_properties);
726 static const TypeInfo virtio_mmio_info = {
727 .name = TYPE_VIRTIO_MMIO,
728 .parent = TYPE_SYS_BUS_DEVICE,
729 .instance_size = sizeof(VirtIOMMIOProxy),
730 .class_init = virtio_mmio_class_init,
733 /* virtio-mmio-bus. */
735 static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
737 BusState *virtio_mmio_bus;
738 VirtIOMMIOProxy *virtio_mmio_proxy;
739 char *proxy_path;
740 char *path;
741 MemoryRegionSection section;
743 virtio_mmio_bus = qdev_get_parent_bus(dev);
744 virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
745 proxy_path = qdev_get_dev_path(DEVICE(virtio_mmio_proxy));
748 * If @format_transport_address is false, then we just perform the same as
749 * virtio_bus_get_dev_path(): we delegate the address formatting for the
750 * device on the virtio-mmio bus to the bus that the virtio-mmio proxy
751 * (i.e., the device that implements the virtio-mmio bus) resides on. In
752 * this case the base address of the virtio-mmio transport will be
753 * invisible.
755 if (!virtio_mmio_proxy->format_transport_address) {
756 return proxy_path;
759 /* Otherwise, we append the base address of the transport. */
760 section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
761 assert(section.mr);
763 if (proxy_path) {
764 path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
765 section.offset_within_address_space);
766 } else {
767 path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
768 section.offset_within_address_space);
770 memory_region_unref(section.mr);
772 g_free(proxy_path);
773 return path;
776 static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
778 BusClass *bus_class = BUS_CLASS(klass);
779 VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
781 k->notify = virtio_mmio_update_irq;
782 k->save_config = virtio_mmio_save_config;
783 k->load_config = virtio_mmio_load_config;
784 k->save_extra_state = virtio_mmio_save_extra_state;
785 k->load_extra_state = virtio_mmio_load_extra_state;
786 k->has_extra_state = virtio_mmio_has_extra_state;
787 k->set_guest_notifiers = virtio_mmio_set_guest_notifiers;
788 k->ioeventfd_enabled = virtio_mmio_ioeventfd_enabled;
789 k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
790 k->pre_plugged = virtio_mmio_pre_plugged;
791 k->has_variable_vring_alignment = true;
792 bus_class->max_dev = 1;
793 bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
796 static const TypeInfo virtio_mmio_bus_info = {
797 .name = TYPE_VIRTIO_MMIO_BUS,
798 .parent = TYPE_VIRTIO_BUS,
799 .instance_size = sizeof(VirtioBusState),
800 .class_init = virtio_mmio_bus_class_init,
803 static void virtio_mmio_register_types(void)
805 type_register_static(&virtio_mmio_bus_info);
806 type_register_static(&virtio_mmio_info);
809 type_init(virtio_mmio_register_types)